From 17da3a4725499d357b78ad32045c8ce1914ab864 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 17:40:27 +0200 Subject: [PATCH 01/10] [DataTables] Add DataTables UX integration --- src/DataTables/.gitattributes | 8 + src/DataTables/.gitignore | 4 + src/DataTables/LICENSE | 19 +++ src/DataTables/README.md | 30 ++++ src/DataTables/assets/dist/controller.d.ts | 9 ++ src/DataTables/assets/dist/controller.js | 33 ++++ src/DataTables/assets/package.json | 33 ++++ src/DataTables/assets/src/controller.ts | 49 ++++++ src/DataTables/composer.json | 53 +++++++ src/DataTables/doc/index.rst | 146 ++++++++++++++++++ src/DataTables/phpunit.xml.dist | 31 ++++ .../src/Builder/DataTableBuilder.php | 13 ++ .../src/Builder/DataTableBuilderInterface.php | 10 ++ src/DataTables/src/DataTablesBundle.php | 13 ++ .../DataTablesExtension.php | 66 ++++++++ src/DataTables/src/Model/DataTable.php | 51 ++++++ .../src/Twig/DataTablesExtension.php | 53 +++++++ src/DataTables/tests/DataTablesBundleTest.php | 16 ++ src/DataTables/tests/Kernel/TwigAppKernel.php | 30 ++++ .../tests/Twig/DataTablesExtensionTest.php | 43 ++++++ 20 files changed, 710 insertions(+) create mode 100644 src/DataTables/.gitattributes create mode 100644 src/DataTables/.gitignore create mode 100644 src/DataTables/LICENSE create mode 100644 src/DataTables/README.md create mode 100644 src/DataTables/assets/dist/controller.d.ts create mode 100644 src/DataTables/assets/dist/controller.js create mode 100644 src/DataTables/assets/package.json create mode 100644 src/DataTables/assets/src/controller.ts create mode 100644 src/DataTables/composer.json create mode 100644 src/DataTables/doc/index.rst create mode 100644 src/DataTables/phpunit.xml.dist create mode 100644 src/DataTables/src/Builder/DataTableBuilder.php create mode 100644 src/DataTables/src/Builder/DataTableBuilderInterface.php create mode 100644 src/DataTables/src/DataTablesBundle.php create mode 100644 src/DataTables/src/DependencyInjection/DataTablesExtension.php create mode 100644 src/DataTables/src/Model/DataTable.php create mode 100644 src/DataTables/src/Twig/DataTablesExtension.php create mode 100644 src/DataTables/tests/DataTablesBundleTest.php create mode 100644 src/DataTables/tests/Kernel/TwigAppKernel.php create mode 100644 src/DataTables/tests/Twig/DataTablesExtensionTest.php diff --git a/src/DataTables/.gitattributes b/src/DataTables/.gitattributes new file mode 100644 index 00000000000..1ba1a889ab8 --- /dev/null +++ b/src/DataTables/.gitattributes @@ -0,0 +1,8 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/.symfony.bundle.yaml export-ignore +/assets/src export-ignore +/assets/test export-ignore +/assets/vitest.config.js export-ignore +/phpunit.xml.dist export-ignore +/tests export-ignore diff --git a/src/DataTables/.gitignore b/src/DataTables/.gitignore new file mode 100644 index 00000000000..bb17c3e124c --- /dev/null +++ b/src/DataTables/.gitignore @@ -0,0 +1,4 @@ +/vendor/ +.phpunit.result.cache +.php_cs.cache +composer.lock diff --git a/src/DataTables/LICENSE b/src/DataTables/LICENSE new file mode 100644 index 00000000000..0ed3a246553 --- /dev/null +++ b/src/DataTables/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/DataTables/README.md b/src/DataTables/README.md new file mode 100644 index 00000000000..5170680fb93 --- /dev/null +++ b/src/DataTables/README.md @@ -0,0 +1,30 @@ +# Symfony UX DataTables + +Symfony UX DataTables is a Symfony bundle integrating the [DataTables](https://datatables.net/) +library in Symfony applications. It is part of [the Symfony UX initiative](https://ux.symfony.com/). + +**This repository is a READ-ONLY sub-tree split**. See +https://github.com/symfony/ux to create issues or submit pull requests. + +## Sponsor + +The Symfony UX packages are [backed][1] by [Mercure.rocks][2]. + +Create real-time experiences in minutes! Mercure.rocks provides a realtime API service +that is tightly integrated with Symfony: create UIs that update in live with UX Turbo, +send notifications with the Notifier component, expose async APIs with API Platform and +create low level stuffs with the Mercure component. We maintain and scale the complex +infrastructure for you! + +Help Symfony by [sponsoring][3] its development! + +## Resources + +- [Documentation](https://symfony.com/bundles/ux-datatables/current/index.html) +- [Report issues](https://github.com/symfony/ux/issues) and + [send Pull Requests](https://github.com/symfony/ux/pulls) + in the [main Symfony UX repository](https://github.com/symfony/ux) + +[1]: https://symfony.com/backers +[2]: https://mercure.rocks +[3]: https://symfony.com/sponsor diff --git a/src/DataTables/assets/dist/controller.d.ts b/src/DataTables/assets/dist/controller.d.ts new file mode 100644 index 00000000000..9b31f62867d --- /dev/null +++ b/src/DataTables/assets/dist/controller.d.ts @@ -0,0 +1,9 @@ +import { Controller } from '@hotwired/stimulus'; +export default class extends Controller { + readonly viewValue: any; + static values: { + view: ObjectConstructor; + }; + connect(): void; + private dispatchEvent; +} diff --git a/src/DataTables/assets/dist/controller.js b/src/DataTables/assets/dist/controller.js new file mode 100644 index 00000000000..50fd15f5fc4 --- /dev/null +++ b/src/DataTables/assets/dist/controller.js @@ -0,0 +1,33 @@ +import { Controller } from '@hotwired/stimulus'; +import DataTable from 'datatables.net-dt'; + +let isDataTableInitialized = false; +class default_1 extends Controller { + constructor() { + super(...arguments); + this.table = null; + } + connect() { + if (isDataTableInitialized) { + return; + } + if (!(this.element instanceof HTMLTableElement)) { + throw new Error('Invalid element'); + } + const payload = this.viewValue; + this.dispatchEvent('pre-connect', { + config: payload, + }); + this.table = new DataTable(this.element, payload); + this.dispatchEvent('connect', { table: this.table }); + isDataTableInitialized = true; + } + dispatchEvent(name, payload) { + this.dispatch(name, { detail: payload, prefix: 'datatables' }); + } +} +default_1.values = { + view: Object, +}; + +export { default_1 as default }; diff --git a/src/DataTables/assets/package.json b/src/DataTables/assets/package.json new file mode 100644 index 00000000000..f33b879430c --- /dev/null +++ b/src/DataTables/assets/package.json @@ -0,0 +1,33 @@ +{ + "name": "@symfony/ux-datatables", + "description": "DataTables integration for Symfony", + "license": "MIT", + "version": "1.0.0", + "type": "module", + "main": "dist/controller.js", + "symfony": { + "controllers": { + "datatable": { + "main": "dist/controller.js", + "webpackMode": "eager", + "fetch": "eager", + "enabled": true, + "autoimport": { + "datatables.net-dt/css/dataTables.dataTables.min.css": true + } + } + }, + "importmap": { + "@hotwired/stimulus": "^3.0.0", + "datatables.net-dt": "^2.1.5" + } + }, + "peerDependencies": { + "@hotwired/stimulus": "^3.0.0", + "datatables.net-dt": "^2.1.5" + }, + "devDependencies": { + "@hotwired/stimulus": "^3.0.0", + "datatables.net-dt": "^2.1.5" + } +} \ No newline at end of file diff --git a/src/DataTables/assets/src/controller.ts b/src/DataTables/assets/src/controller.ts new file mode 100644 index 00000000000..5903f5f2a54 --- /dev/null +++ b/src/DataTables/assets/src/controller.ts @@ -0,0 +1,49 @@ +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Controller } from '@hotwired/stimulus'; +import DataTable from 'datatables.net-dt'; + +let isDataTableInitialized = false; + +export default class extends Controller { + declare readonly viewValue: any; + + static values = { + view: Object, + }; + + private table: DataTable | null = null; + + connect() { + if (isDataTableInitialized) { + return; + } + + if (!(this.element instanceof HTMLTableElement)) { + throw new Error('Invalid element'); + } + + const payload = this.viewValue; + + this.dispatchEvent('pre-connect', { + config: payload, + }) + + new DataTable(this.element as HTMLElement, payload); + + this.dispatchEvent('connect', { table: this.table }); + + isDataTableInitialized = true; + } + + private dispatchEvent(name: string, payload: any) { + this.dispatch(name, { detail: payload, prefix: 'datatables' }); + } +} \ No newline at end of file diff --git a/src/DataTables/composer.json b/src/DataTables/composer.json new file mode 100644 index 00000000000..a93d8bea15a --- /dev/null +++ b/src/DataTables/composer.json @@ -0,0 +1,53 @@ +{ + "name": "symfony/ux-datatables", + "type": "symfony-bundle", + "description": "DataTables.net integration for Symfony", + "keywords": [ + "symfony-ux" + ], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Tanguy LemariƩ", + "email": "tanguy.lemarie6@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "autoload": { + "psr-4": { + "Symfony\\UX\\DataTables\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Symfony\\UX\\DataTables\\Tests\\": "tests/" + } + }, + "require": { + "php": ">=8.1", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/stimulus-bundle": "^2.9.1" + }, + "require-dev": { + "symfony/framework-bundle": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/flex": "<1.13" + }, + "extra": { + "thanks": { + "name": "symfony/ux", + "url": "https://github.com/symfony/ux" + } + }, + "minimum-stability": "dev" +} diff --git a/src/DataTables/doc/index.rst b/src/DataTables/doc/index.rst new file mode 100644 index 00000000000..c4d7ba4a93b --- /dev/null +++ b/src/DataTables/doc/index.rst @@ -0,0 +1,146 @@ +Symfony UX DataTables +===================== + +Symfony UX DataTables is a Symfony bundle integrating the +`DataTables`_ library in Symfony applications. +It is part of `the Symfony UX initiative`_. + +Installation +------------ + +.. caution:: + + Before you start, make sure you have `StimulusBundle configured in your app`_. + +Install the bundle using Composer and Symfony Flex: + +.. code-block:: terminal + + $ composer require symfony/ux-datatables + +If you're using WebpackEncore, install your assets and restart Encore (not +needed if you're using AssetMapper): + +.. code-block:: terminal + + $ npm install --force + $ npm run watch + + # or use yarn + $ yarn install --force + $ yarn watch + +Usage +----- + +To use Symfony UX DataTables, inject the ``DataTableBuilderInterface`` service +and create tables in PHP:: + + // ... + use Symfony\UX\DataTables\Builder\DataTableBuilderInterface; + use Symfony\UX\DataTables\Model\DataTable; + + class HomeController extends AbstractController + { + #[Route('/', name: 'app_homepage')] + public function index(DataTableBuilderInterface $tableBuilder): Response + { + $table= $tableBuilder->('usersTable'); + + $table->setData([ + 'columns' => ['First name', 'Last name'], + 'data' => [ + ['John', 'Doe'], + ['Jane', 'Smith'], + ], + ]); + + $table->setOptions([ + 'order' => [ + ['idx': 1, 'dir': 'asc'] + ], + ]); + + return $this->render('home/index.html.twig', [ + 'table' => $table, + ]); + } + } + +All options and data are provided as-is to DataTables. You can read +`DataTables documentation`_ to discover them all. + +Once created in PHP, a table can be displayed using Twig: + +.. code-block:: html+twig + + {{ render_datatable(table) }} + + {# You can pass HTML attributes as a second argument to add them on the tag #} + {{ render_datatable(table, {'class': 'my-table'}) }} + +Extend the default behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Symfony UX DataTables allows you to extend its default behavior using a +custom Stimulus controller: + +.. code-block:: javascript + + // mytable_controller.js + + import { Controller } from '@hotwired/stimulus'; + + export default class extends Controller { + connect() { + this.element.addEventListener('datatables:pre-connect', this._onPreConnect); + this.element.addEventListener('datatables:connect', this._onConnect); + } + + disconnect() { + // You should always remove listeners when the controller is disconnected to avoid side effects + this.element.removeEventListener('datatables:pre-connect', this._onPreConnect); + this.element.removeEventListener('datatables:connect', this._onConnect); + } + + _onPreConnect(event) { + // The table is not yet created + // You can access the config that will be passed to "new DataTable()" + console.log(event.detail.config); + + // For instance you can define a render callback for a given column + event.detail.config.columns[0].render = function (data, type, row, meta) { + return 'Download'; + } + } + + _onConnect(event) { + // The table was just created + console.log(event.detail.table); // You can access the table instance using the event details + + // For instance you can listen to additional events + event.detail.table.on('init', (event) => { + /* ... */ + }; + event.detail.table.on('draw', (event) => { + /* ... */ + }; + } + } + +Then in your render call, add your controller as an HTML attribute: + +.. code-block:: twig + + {{ render_datatable(table, {'data-controller': 'mytable'}) }} + +Backward Compatibility promise +------------------------------ + +This bundle aims at following the same Backward Compatibility promise as +the Symfony framework: https://symfony.com/doc/current/contributing/code/bc.html. + +.. _`DataTables`: https://datatables.net +.. _`the Symfony UX initiative`: https://ux.symfony.com/ +.. _`DataTables documentation`: https://datatables.net/manual/ +.. _StimulusBundle configured in your app: https://symfony.com/bundles/StimulusBundle/current/index.html \ No newline at end of file diff --git a/src/DataTables/phpunit.xml.dist b/src/DataTables/phpunit.xml.dist new file mode 100644 index 00000000000..ba15dfc214b --- /dev/null +++ b/src/DataTables/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + tests + + + + + + ./src + + + diff --git a/src/DataTables/src/Builder/DataTableBuilder.php b/src/DataTables/src/Builder/DataTableBuilder.php new file mode 100644 index 00000000000..1adcd6b25e6 --- /dev/null +++ b/src/DataTables/src/Builder/DataTableBuilder.php @@ -0,0 +1,13 @@ +setDefinition('datatables.builder', new Definition(DataTableBuilder::class)) + ->setPublic(false) + ; + + $container + ->setAlias(DataTableBuilderInterface::class, 'datatables.builder') + ->setPublic(false) + ; + + $container + ->setDefinition('datatables.twig_extension', new Definition(DataTableExtension::class)) + ->addArgument(new Reference('stimulus.helper')) + ->addTag('twig.extension') + ->setPublic(false) + ; + } + + public function prepend(ContainerBuilder $container): void + { + if (!$this->isAssetMapperAvailable($container)) { + return; + } + + $container->prependExtensionConfig('framework', [ + 'asset_mapper' => [ + 'paths' => [ + __DIR__.'/../../assets/dist' => '@symfony/ux-datatables', + ], + ], + ]); + } + + private function isAssetMapperAvailable(ContainerBuilder $container): bool + { + if (!interface_exists(AssetMapperInterface::class)) { + return false; + } + + // check that FrameworkBundle 6.3 or higher is installed + $bundlesMetadata = $container->getParameter('kernel.bundles_metadata'); + if (!isset($bundlesMetadata['FrameworkBundle'])) { + return false; + } + + return is_file($bundlesMetadata['FrameworkBundle']['path'].'/Resources/config/asset_mapper.php'); + } +} diff --git a/src/DataTables/src/Model/DataTable.php b/src/DataTables/src/Model/DataTable.php new file mode 100644 index 00000000000..0e673a25d87 --- /dev/null +++ b/src/DataTables/src/Model/DataTable.php @@ -0,0 +1,51 @@ +id = $id; + } + + public function getId(): ?string + { + return $this->id; + } + + public function getOptions(): array + { + return $this->options; + } + + public function setOptions(array $options): static + { + $this->options = $options; + + return $this; + } + + public function getAttributes(): array + { + return $this->attributes; + } + + public function setAttributes(array $attributes): static + { + $this->attributes = $attributes; + + return $this; + } + + public function getDataController(): ?string + { + return $this->attributes['data-controller'] ?? null; + } +} diff --git a/src/DataTables/src/Twig/DataTablesExtension.php b/src/DataTables/src/Twig/DataTablesExtension.php new file mode 100644 index 00000000000..5da74f38bc8 --- /dev/null +++ b/src/DataTables/src/Twig/DataTablesExtension.php @@ -0,0 +1,53 @@ + ['html']]), + ]; + } + + public function renderDataTable(DataTable $table, array $attributes = []): string + { + $table->setAttributes(array_merge($table->getAttributes(), $attributes)); + + $controllers = []; + if ($table->getDataController()) { + $controllers[$table->getDataController()] = []; + } + $controllers['@symfony/ux-datatables/datatable'] = ['view' => $table->getOptions()]; + + $stimulusAttributes = $this->stimulus->createStimulusAttributes(); + foreach ($controllers as $name => $controllerValues) { + $stimulusAttributes->addController($name, $controllerValues); + } + + foreach ($table->getAttributes() as $name => $value) { + if ('data-controller' === $name) { + continue; + } + + if (true === $value) { + $stimulusAttributes->addAttribute($name, $name); + } elseif (false !== $value) { + $stimulusAttributes->addAttribute($name, $value); + } + } + + return \sprintf('
', $table->getId(), $stimulusAttributes); + } +} diff --git a/src/DataTables/tests/DataTablesBundleTest.php b/src/DataTables/tests/DataTablesBundleTest.php new file mode 100644 index 00000000000..a7651d40e79 --- /dev/null +++ b/src/DataTables/tests/DataTablesBundleTest.php @@ -0,0 +1,16 @@ +boot(); + $this->assertArrayHasKey('DataTablesBundle', $kernel->getBundles()); + } +} \ No newline at end of file diff --git a/src/DataTables/tests/Kernel/TwigAppKernel.php b/src/DataTables/tests/Kernel/TwigAppKernel.php new file mode 100644 index 00000000000..2e8254cd68c --- /dev/null +++ b/src/DataTables/tests/Kernel/TwigAppKernel.php @@ -0,0 +1,30 @@ +load(function (ContainerBuilder $container) { + $container->loadFromExtension('framework', ['secret' => '$ecret', 'test' => true, 'http_method_override' => false]); + $container->loadFromExtension('twig', ['default_path' => __DIR__.'/templates', 'strict_variables' => true, 'exception_controller' => null]); + + $container->setAlias('test.datatables.builder', 'datatables.builder')->setPublic(true); + $container->setAlias('test.datatables.twig_extension', 'datatables.twig_extension')->setPublic(true); + }); + } +} \ No newline at end of file diff --git a/src/DataTables/tests/Twig/DataTablesExtensionTest.php b/src/DataTables/tests/Twig/DataTablesExtensionTest.php new file mode 100644 index 00000000000..648a8ad21f5 --- /dev/null +++ b/src/DataTables/tests/Twig/DataTablesExtensionTest.php @@ -0,0 +1,43 @@ +boot(); + $container = $kernel->getContainer()->get('test.service_container'); + + /** @var DataTableBuilderInterface $builder */ + $builder = $container->get('test.datatables.builder'); + + $table = $builder->createDataTable('table'); + + $table->setOptions([ + 'columns' => [ + ['title' => 'Column 1'], + ['title' => 'Column 2'], + ], + 'data' => [ + ['Row 1 Column 1', 'Row 1 Column 2'], + ['Row 2 Column 1', 'Row 2 Column 2'], + ], + ]); + + $rendered = $container->get('test.datatables.twig_extension')->renderDataTable( + $table, + ['data-controller' => 'mycontroller', 'class' => 'myclass'] + ); + + $this->assertSame( + expected: '
', + actual: $rendered + ); + } +} \ No newline at end of file From e085f82aee121080af692e3600134abeb1f18165 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 17:58:54 +0200 Subject: [PATCH 02/10] [DataTables] Coding Standard and lint --- src/DataTables/assets/src/controller.ts | 2 +- src/DataTables/src/Builder/DataTableBuilder.php | 9 +++++++++ .../src/Builder/DataTableBuilderInterface.php | 9 +++++++++ src/DataTables/src/DataTablesBundle.php | 9 +++++++++ .../src/DependencyInjection/DataTablesExtension.php | 9 +++++++++ src/DataTables/src/Model/DataTable.php | 9 +++++++++ src/DataTables/src/Twig/DataTablesExtension.php | 9 +++++++++ src/DataTables/tests/DataTablesBundleTest.php | 11 ++++++++++- .../tests/Twig/DataTablesExtensionTest.php | 13 +++++++++++-- 9 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/DataTables/assets/src/controller.ts b/src/DataTables/assets/src/controller.ts index 5903f5f2a54..ef03cfe5cf7 100644 --- a/src/DataTables/assets/src/controller.ts +++ b/src/DataTables/assets/src/controller.ts @@ -34,7 +34,7 @@ export default class extends Controller { this.dispatchEvent('pre-connect', { config: payload, - }) + }); new DataTable(this.element as HTMLElement, payload); diff --git a/src/DataTables/src/Builder/DataTableBuilder.php b/src/DataTables/src/Builder/DataTableBuilder.php index 1adcd6b25e6..8bb532b1307 100644 --- a/src/DataTables/src/Builder/DataTableBuilder.php +++ b/src/DataTables/src/Builder/DataTableBuilder.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\Builder; use Symfony\UX\DataTables\Model\DataTable; diff --git a/src/DataTables/src/Builder/DataTableBuilderInterface.php b/src/DataTables/src/Builder/DataTableBuilderInterface.php index cc3fca2498d..20393d20211 100644 --- a/src/DataTables/src/Builder/DataTableBuilderInterface.php +++ b/src/DataTables/src/Builder/DataTableBuilderInterface.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\Builder; use Symfony\UX\DataTables\Model\DataTable; diff --git a/src/DataTables/src/DataTablesBundle.php b/src/DataTables/src/DataTablesBundle.php index 7abfa1d0623..8282e7b880d 100644 --- a/src/DataTables/src/DataTablesBundle.php +++ b/src/DataTables/src/DataTablesBundle.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/DataTables/src/DependencyInjection/DataTablesExtension.php b/src/DataTables/src/DependencyInjection/DataTablesExtension.php index fc76378ab2e..8d9d0593cd2 100644 --- a/src/DataTables/src/DependencyInjection/DataTablesExtension.php +++ b/src/DataTables/src/DependencyInjection/DataTablesExtension.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\DependencyInjection; use Symfony\Component\AssetMapper\AssetMapperInterface; diff --git a/src/DataTables/src/Model/DataTable.php b/src/DataTables/src/Model/DataTable.php index 0e673a25d87..5344718c040 100644 --- a/src/DataTables/src/Model/DataTable.php +++ b/src/DataTables/src/Model/DataTable.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\Model; class DataTable diff --git a/src/DataTables/src/Twig/DataTablesExtension.php b/src/DataTables/src/Twig/DataTablesExtension.php index 5da74f38bc8..07e50b220db 100644 --- a/src/DataTables/src/Twig/DataTablesExtension.php +++ b/src/DataTables/src/Twig/DataTablesExtension.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\Twig; use Symfony\UX\DataTables\Model\DataTable; diff --git a/src/DataTables/tests/DataTablesBundleTest.php b/src/DataTables/tests/DataTablesBundleTest.php index a7651d40e79..8424a0ae2ed 100644 --- a/src/DataTables/tests/DataTablesBundleTest.php +++ b/src/DataTables/tests/DataTablesBundleTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\Tests; use PHPUnit\Framework\TestCase; @@ -13,4 +22,4 @@ public function testBootKernel() $kernel->boot(); $this->assertArrayHasKey('DataTablesBundle', $kernel->getBundles()); } -} \ No newline at end of file +} diff --git a/src/DataTables/tests/Twig/DataTablesExtensionTest.php b/src/DataTables/tests/Twig/DataTablesExtensionTest.php index 648a8ad21f5..46c8b748d7a 100644 --- a/src/DataTables/tests/Twig/DataTablesExtensionTest.php +++ b/src/DataTables/tests/Twig/DataTablesExtensionTest.php @@ -1,6 +1,15 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\UX\DataTables\Tests\Twig; use PHPUnit\Framework\TestCase; use Symfony\UX\DataTables\Builder\DataTableBuilderInterface; @@ -40,4 +49,4 @@ public function testRenderDataTable(): void actual: $rendered ); } -} \ No newline at end of file +} From e8449ad4917a4100a9a740f086bf473174ea85c0 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 18:11:31 +0200 Subject: [PATCH 03/10] [DataTables] Fix DataTablesExtensionTest class name and JS Coding Style --- src/DataTables/assets/package.json | 2 +- src/DataTables/assets/src/controller.ts | 2 +- src/DataTables/tests/Twig/DataTablesExtensionTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DataTables/assets/package.json b/src/DataTables/assets/package.json index f33b879430c..9675f174a2c 100644 --- a/src/DataTables/assets/package.json +++ b/src/DataTables/assets/package.json @@ -30,4 +30,4 @@ "@hotwired/stimulus": "^3.0.0", "datatables.net-dt": "^2.1.5" } -} \ No newline at end of file +} diff --git a/src/DataTables/assets/src/controller.ts b/src/DataTables/assets/src/controller.ts index ef03cfe5cf7..9f652d00b1b 100644 --- a/src/DataTables/assets/src/controller.ts +++ b/src/DataTables/assets/src/controller.ts @@ -46,4 +46,4 @@ export default class extends Controller { private dispatchEvent(name: string, payload: any) { this.dispatch(name, { detail: payload, prefix: 'datatables' }); } -} \ No newline at end of file +} diff --git a/src/DataTables/tests/Twig/DataTablesExtensionTest.php b/src/DataTables/tests/Twig/DataTablesExtensionTest.php index 46c8b748d7a..4ad40940922 100644 --- a/src/DataTables/tests/Twig/DataTablesExtensionTest.php +++ b/src/DataTables/tests/Twig/DataTablesExtensionTest.php @@ -15,7 +15,7 @@ use Symfony\UX\DataTables\Builder\DataTableBuilderInterface; use Symfony\UX\DataTables\Tests\Kernel\TwigAppKernel; -class DataTableExtensionTest extends TestCase +class DataTablesExtensionTest extends TestCase { public function testRenderDataTable(): void { From f621c35cbe01c507691f90b443e5ee6ecc7f2d70 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 18:16:28 +0200 Subject: [PATCH 04/10] [DataTables] PHP Coding Standard --- .../src/DependencyInjection/DataTablesExtension.php | 2 +- src/DataTables/src/Twig/DataTablesExtension.php | 4 ++-- src/DataTables/tests/Kernel/TwigAppKernel.php | 9 +++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/DataTables/src/DependencyInjection/DataTablesExtension.php b/src/DataTables/src/DependencyInjection/DataTablesExtension.php index 8d9d0593cd2..ee6789adbfd 100644 --- a/src/DataTables/src/DependencyInjection/DataTablesExtension.php +++ b/src/DataTables/src/DependencyInjection/DataTablesExtension.php @@ -36,7 +36,7 @@ public function load(array $configs, ContainerBuilder $container): void ; $container - ->setDefinition('datatables.twig_extension', new Definition(DataTableExtension::class)) + ->setDefinition('datatables.twig_extension', new Definition(DataTablesExtension::class)) ->addArgument(new Reference('stimulus.helper')) ->addTag('twig.extension') ->setPublic(false) diff --git a/src/DataTables/src/Twig/DataTablesExtension.php b/src/DataTables/src/Twig/DataTablesExtension.php index 07e50b220db..5857279a684 100644 --- a/src/DataTables/src/Twig/DataTablesExtension.php +++ b/src/DataTables/src/Twig/DataTablesExtension.php @@ -16,10 +16,10 @@ use Twig\Extension\AbstractExtension; use Twig\TwigFunction; -class DataTableExtension extends AbstractExtension +class DataTablesExtension extends AbstractExtension { public function __construct( - private StimulusHelper $stimulus + private StimulusHelper $stimulus, ) { } diff --git a/src/DataTables/tests/Kernel/TwigAppKernel.php b/src/DataTables/tests/Kernel/TwigAppKernel.php index 2e8254cd68c..81bcc8525a5 100644 --- a/src/DataTables/tests/Kernel/TwigAppKernel.php +++ b/src/DataTables/tests/Kernel/TwigAppKernel.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\UX\DataTables\Tests\Kernel; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; From 3cacce396b7e16ba694203ee990355a24f4ee733 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 18:22:41 +0200 Subject: [PATCH 05/10] [DataTables] Review fixes --- src/DataTables/assets/dist/controller.js | 5 ++- src/DataTables/assets/package.json | 56 ++++++++++++------------ src/DataTables/assets/src/controller.ts | 7 +-- src/DataTables/doc/index.rst | 4 +- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/DataTables/assets/dist/controller.js b/src/DataTables/assets/dist/controller.js index 50fd15f5fc4..c1f71daaf57 100644 --- a/src/DataTables/assets/dist/controller.js +++ b/src/DataTables/assets/dist/controller.js @@ -6,9 +6,10 @@ class default_1 extends Controller { constructor() { super(...arguments); this.table = null; + this.isDataTableInitialized = false; } connect() { - if (isDataTableInitialized) { + if (this.isDataTableInitialized) { return; } if (!(this.element instanceof HTMLTableElement)) { @@ -20,7 +21,7 @@ class default_1 extends Controller { }); this.table = new DataTable(this.element, payload); this.dispatchEvent('connect', { table: this.table }); - isDataTableInitialized = true; + this.isDataTableInitialized = true; } dispatchEvent(name, payload) { this.dispatch(name, { detail: payload, prefix: 'datatables' }); diff --git a/src/DataTables/assets/package.json b/src/DataTables/assets/package.json index 9675f174a2c..d760d2ee118 100644 --- a/src/DataTables/assets/package.json +++ b/src/DataTables/assets/package.json @@ -1,33 +1,33 @@ { - "name": "@symfony/ux-datatables", - "description": "DataTables integration for Symfony", - "license": "MIT", - "version": "1.0.0", - "type": "module", - "main": "dist/controller.js", - "symfony": { - "controllers": { - "datatable": { - "main": "dist/controller.js", - "webpackMode": "eager", - "fetch": "eager", - "enabled": true, - "autoimport": { - "datatables.net-dt/css/dataTables.dataTables.min.css": true + "name": "@symfony/ux-datatables", + "description": "DataTables integration for Symfony", + "license": "MIT", + "version": "1.0.0", + "type": "module", + "main": "dist/controller.js", + "symfony": { + "controllers": { + "datatable": { + "main": "dist/controller.js", + "webpackMode": "eager", + "fetch": "eager", + "enabled": true, + "autoimport": { + "datatables.net-dt/css/dataTables.dataTables.min.css": true + } + } + }, + "importmap": { + "@hotwired/stimulus": "^3.0.0", + "datatables.net-dt": "^2.1.5" } - } }, - "importmap": { - "@hotwired/stimulus": "^3.0.0", - "datatables.net-dt": "^2.1.5" + "peerDependencies": { + "@hotwired/stimulus": "^3.0.0", + "datatables.net-dt": "^2.1.5" + }, + "devDependencies": { + "@hotwired/stimulus": "^3.0.0", + "datatables.net-dt": "^2.1.5" } - }, - "peerDependencies": { - "@hotwired/stimulus": "^3.0.0", - "datatables.net-dt": "^2.1.5" - }, - "devDependencies": { - "@hotwired/stimulus": "^3.0.0", - "datatables.net-dt": "^2.1.5" - } } diff --git a/src/DataTables/assets/src/controller.ts b/src/DataTables/assets/src/controller.ts index 9f652d00b1b..834b84e6d2d 100644 --- a/src/DataTables/assets/src/controller.ts +++ b/src/DataTables/assets/src/controller.ts @@ -20,9 +20,10 @@ export default class extends Controller { }; private table: DataTable | null = null; + private isDataTableInitialized = false; connect() { - if (isDataTableInitialized) { + if (this.isDataTableInitialized) { return; } @@ -36,11 +37,11 @@ export default class extends Controller { config: payload, }); - new DataTable(this.element as HTMLElement, payload); + this.table = new DataTable(this.element as HTMLElement, payload); this.dispatchEvent('connect', { table: this.table }); - isDataTableInitialized = true; + this.isDataTableInitialized = true; } private dispatchEvent(name: string, payload: any) { diff --git a/src/DataTables/doc/index.rst b/src/DataTables/doc/index.rst index c4d7ba4a93b..dfd5b0b67df 100644 --- a/src/DataTables/doc/index.rst +++ b/src/DataTables/doc/index.rst @@ -45,7 +45,7 @@ and create tables in PHP:: #[Route('/', name: 'app_homepage')] public function index(DataTableBuilderInterface $tableBuilder): Response { - $table= $tableBuilder->('usersTable'); + $table = $tableBuilder->createDataTable('usersTable'); $table->setData([ 'columns' => ['First name', 'Last name'], @@ -57,7 +57,7 @@ and create tables in PHP:: $table->setOptions([ 'order' => [ - ['idx': 1, 'dir': 'asc'] + ['idx' => 1, 'dir' => 'asc'] ], ]); From 83e6bbb1094b47b49f4c18d94762fe52953b5636 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 18:26:39 +0200 Subject: [PATCH 06/10] [DataTables] Remove unused declaration --- src/DataTables/assets/dist/controller.js | 1 - src/DataTables/assets/src/controller.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/DataTables/assets/dist/controller.js b/src/DataTables/assets/dist/controller.js index c1f71daaf57..409436c2078 100644 --- a/src/DataTables/assets/dist/controller.js +++ b/src/DataTables/assets/dist/controller.js @@ -1,7 +1,6 @@ import { Controller } from '@hotwired/stimulus'; import DataTable from 'datatables.net-dt'; -let isDataTableInitialized = false; class default_1 extends Controller { constructor() { super(...arguments); diff --git a/src/DataTables/assets/src/controller.ts b/src/DataTables/assets/src/controller.ts index 834b84e6d2d..0a8e7c9ecca 100644 --- a/src/DataTables/assets/src/controller.ts +++ b/src/DataTables/assets/src/controller.ts @@ -10,8 +10,6 @@ import { Controller } from '@hotwired/stimulus'; import DataTable from 'datatables.net-dt'; -let isDataTableInitialized = false; - export default class extends Controller { declare readonly viewValue: any; From 1fbc1eb8e09282c5418f809887e54ae0fe85f3c9 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 18:29:38 +0200 Subject: [PATCH 07/10] [DataTables] Fix DataTablesExtension container definition --- src/DataTables/src/DependencyInjection/DataTablesExtension.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/DataTables/src/DependencyInjection/DataTablesExtension.php b/src/DataTables/src/DependencyInjection/DataTablesExtension.php index ee6789adbfd..c3bd82f2d0e 100644 --- a/src/DataTables/src/DependencyInjection/DataTablesExtension.php +++ b/src/DataTables/src/DependencyInjection/DataTablesExtension.php @@ -19,7 +19,6 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\UX\DataTables\Builder\DataTableBuilder; use Symfony\UX\DataTables\Builder\DataTableBuilderInterface; -use Symfony\UX\DataTables\Twig\DataTableExtension; class DataTablesExtension extends Extension implements PrependExtensionInterface { @@ -36,7 +35,7 @@ public function load(array $configs, ContainerBuilder $container): void ; $container - ->setDefinition('datatables.twig_extension', new Definition(DataTablesExtension::class)) + ->setDefinition('datatables.twig_extension', new Definition(\Symfony\UX\DataTables\Twig\DataTablesExtension::class)) ->addArgument(new Reference('stimulus.helper')) ->addTag('twig.extension') ->setPublic(false) From 0b48b0cb11c3c5f8a0866ac8977dbc0ff4598284 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 19:31:08 +0200 Subject: [PATCH 08/10] [DataTables] Add controller.test.ts --- src/DataTables/assets/test/controller.test.ts | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/DataTables/assets/test/controller.test.ts diff --git a/src/DataTables/assets/test/controller.test.ts b/src/DataTables/assets/test/controller.test.ts new file mode 100644 index 00000000000..75dd52c2866 --- /dev/null +++ b/src/DataTables/assets/test/controller.test.ts @@ -0,0 +1,81 @@ +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Application } from '@hotwired/stimulus'; +import { waitFor } from '@testing-library/dom'; +import DataTableController from '../src/controller'; + +const startDataTableTest = async (tableHtml: string): Promise<{ table: HTMLTableElement; dataTable: DataTable }> => { + let dataTable: DataTable | null = null; + + document.body.addEventListener('datatables:pre-connect', () => { + document.body.classList.add('pre-connected'); + }); + + document.body.addEventListener('datatables:connect', (event: any) => { + dataTable = event.detail.table; + document.body.classList.add('connected'); + }); + + document.body.innerHTML = tableHtml; + + const tableElement = document.querySelector('table'); + if (!tableElement) { + throw 'Missing table element'; + } + + await waitFor(() => { + expect(document.body).toHaveClass('pre-connected'); + expect(document.body).toHaveClass('connected'); + }); + + if (!dataTable) { + throw 'Missing DataTable instance'; + } + + return { table: tableElement, dataTable }; +}; + +describe('DataTableController', () => { + beforeAll(() => { + const application = Application.start(); + application.register('datatables', DataTableController); + }); + + afterEach(() => { + document.body.innerHTML = ''; + }); + + it('connect without data', async () => { + const { dataTable } = await startDataTableTest(` +
+ `); + + expect(dataTable.data().toArray()).toEqual([]); + }); + + it('connect with data', async () => { + const { dataTable } = await startDataTableTest(` +
+ `); + + expect(dataTable.data().toArray()).toEqual([ + ['John', 'Doe'], + ['Jane', 'Smith'], + ]); + }); +}); \ No newline at end of file From 16f4976a9b383da29f7bfe99dc8ef42c4d2de3be Mon Sep 17 00:00:00 2001 From: pentiminax Date: Wed, 11 Sep 2024 19:36:40 +0200 Subject: [PATCH 09/10] [DataTables] Run format --- src/DataTables/assets/test/controller.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/DataTables/assets/test/controller.test.ts b/src/DataTables/assets/test/controller.test.ts index 75dd52c2866..7f506af1f26 100644 --- a/src/DataTables/assets/test/controller.test.ts +++ b/src/DataTables/assets/test/controller.test.ts @@ -11,7 +11,9 @@ import { Application } from '@hotwired/stimulus'; import { waitFor } from '@testing-library/dom'; import DataTableController from '../src/controller'; -const startDataTableTest = async (tableHtml: string): Promise<{ table: HTMLTableElement; dataTable: DataTable }> => { +const startDataTableTest = async ( + tableHtml: string +): Promise<{ table: HTMLTableElement; dataTable: DataTable }> => { let dataTable: DataTable | null = null; document.body.addEventListener('datatables:pre-connect', () => { @@ -78,4 +80,4 @@ describe('DataTableController', () => { ['Jane', 'Smith'], ]); }); -}); \ No newline at end of file +}); From 36a581de1f69d12cf34441b5135e67a822933e68 Mon Sep 17 00:00:00 2001 From: Pentiminax Date: Wed, 11 Sep 2024 19:41:12 +0200 Subject: [PATCH 10/10] [DataTables] PHP Coding Standard --- src/DataTables/tests/Kernel/TwigAppKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataTables/tests/Kernel/TwigAppKernel.php b/src/DataTables/tests/Kernel/TwigAppKernel.php index 81bcc8525a5..23cea940fd6 100644 --- a/src/DataTables/tests/Kernel/TwigAppKernel.php +++ b/src/DataTables/tests/Kernel/TwigAppKernel.php @@ -36,4 +36,4 @@ public function registerContainerConfiguration(LoaderInterface $loader): void $container->setAlias('test.datatables.twig_extension', 'datatables.twig_extension')->setPublic(true); }); } -} \ No newline at end of file +}