From 0a6ccbb2a2c25275fc35316e4194fdb268936764 Mon Sep 17 00:00:00 2001 From: Alexandre Castelain Date: Wed, 8 Jan 2025 14:51:38 +0100 Subject: [PATCH 1/6] Add a modal action whose content is loaded via an HTTP call. --- assets/controllers/bootstrap/modal.js | 27 ++++++++ assets/package.json | 7 +- src/Action/Type/ModalActionType.php | 68 +++++++++++++++++++ src/Resources/config/actions.php | 7 ++ src/Resources/views/themes/base.html.twig | 12 ++++ .../views/themes/bootstrap_5.html.twig | 26 +++++++ 6 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 assets/controllers/bootstrap/modal.js create mode 100755 src/Action/Type/ModalActionType.php diff --git a/assets/controllers/bootstrap/modal.js b/assets/controllers/bootstrap/modal.js new file mode 100644 index 00000000..16728a8c --- /dev/null +++ b/assets/controllers/bootstrap/modal.js @@ -0,0 +1,27 @@ +import { Controller } from '@hotwired/stimulus'; +import { Modal } from 'bootstrap'; // Import Bootstrap + +export default class extends Controller { + static targets = ['modal']; + + static values = { + url: String, + } + + open(event) { + event.preventDefault(); + const modalContent = this.modalTarget; + + fetch(this.urlValue) + .then(response => { + if (!response.ok) { + throw new Error('Error loading content.'); + } + return response.text(); + }) + .then(html => { + modalContent.innerHTML = html; + }) + ; + } +} diff --git a/assets/package.json b/assets/package.json index 36305897..ff580e13 100755 --- a/assets/package.json +++ b/assets/package.json @@ -19,6 +19,11 @@ "main": "controllers/state.js", "fetch": "eager", "enabled": true + }, + "bootstrap-modal": { + "main": "controllers/bootstrap/modal.js", + "fetch": "eager", + "enabled": true } }, "importmap": { @@ -34,4 +39,4 @@ "@hotwired/stimulus": "^3.0.0", "sortablejs": "^1.15.0" } -} \ No newline at end of file +} diff --git a/src/Action/Type/ModalActionType.php b/src/Action/Type/ModalActionType.php new file mode 100755 index 00000000..1fdd053c --- /dev/null +++ b/src/Action/Type/ModalActionType.php @@ -0,0 +1,68 @@ +parent instanceof ColumnValueView) { + $value = $view->parent->value; + + foreach (['href', 'route', 'route_params'] as $optionName) { + if (isset($options[$optionName]) && is_callable($options[$optionName])) { + $options[$optionName] = $options[$optionName]($value); + } + } + } else { + foreach (['href', 'route', 'route_params'] as $optionName) { + if (isset($options[$optionName]) && is_callable($options[$optionName])) { + throw new LogicException(sprintf('Callable used for option "%s", but it\'s only available for RowActions.', $optionName)); + } + } + } + + $href = $options['href'] ?? $this->router->generate($options['route'], $options['route_params']); + + $view->vars = array_replace($view->vars, [ + 'href' => $href, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver + ->define('route') + ->allowedTypes('string', 'callable') + ; + + $resolver + ->define('route_params') + ->allowedTypes('array', 'callable') + ->default([]) + ; + + $resolver + ->define('href') + ->allowedTypes('string', 'callable') + ; + } +} diff --git a/src/Resources/config/actions.php b/src/Resources/config/actions.php index 5f76912b..83c31ee9 100755 --- a/src/Resources/config/actions.php +++ b/src/Resources/config/actions.php @@ -10,6 +10,7 @@ use Kreyu\Bundle\DataTableBundle\Action\Type\ButtonActionType; use Kreyu\Bundle\DataTableBundle\Action\Type\FormActionType; use Kreyu\Bundle\DataTableBundle\Action\Type\LinkActionType; +use Kreyu\Bundle\DataTableBundle\Action\Type\ModalActionType; use Kreyu\Bundle\DataTableBundle\Action\Type\ResolvedActionTypeFactory; use Kreyu\Bundle\DataTableBundle\Action\Type\ResolvedActionTypeFactoryInterface; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -60,4 +61,10 @@ ->set('kreyu_data_table.action.type.form', FormActionType::class) ->tag('kreyu_data_table.action.type') ; + + $services + ->set('kreyu_data_table.action.type.modal', ModalActionType::class) + ->tag('kreyu_data_table.action.type') + ->args([service('router')]) + ; }; diff --git a/src/Resources/views/themes/base.html.twig b/src/Resources/views/themes/base.html.twig index fafa635e..b574e748 100755 --- a/src/Resources/views/themes/base.html.twig +++ b/src/Resources/views/themes/base.html.twig @@ -632,6 +632,18 @@ {% endblock %} +{% block action_modal_control %} + {% set attr = { dataUrl }|filter(v => v != null)|merge(attr|default({})) %} + + {% if batch %} + {% set attr = { 'data-kreyu--data-table-bundle--batch-target': 'identifierHolder' }|merge(attr) %} + {% endif %} + + +{% endblock %} + {% block sort_arrow_none %}{% endblock %} {% block sort_arrow_asc %}↑{% endblock %} diff --git a/src/Resources/views/themes/bootstrap_5.html.twig b/src/Resources/views/themes/bootstrap_5.html.twig index 6767e24f..2c0359a8 100755 --- a/src/Resources/views/themes/bootstrap_5.html.twig +++ b/src/Resources/views/themes/bootstrap_5.html.twig @@ -723,6 +723,32 @@ {% endif %} {% endblock %} + +{% block action_modal_control %} +
+ {% set modalId = 'modalId-' ~ random() %} + + + +
+{% endblock %} + {% block sort_arrow_none %} From e23b71b2658c217ec1a568465dd3ca7f9f4a577e Mon Sep 17 00:00:00 2001 From: Alexandre Castelain Date: Thu, 9 Jan 2025 11:31:41 +0100 Subject: [PATCH 2/6] Make the modal work with batch actions --- assets/controllers/batch.js | 11 ++++++++--- assets/package.json | 2 +- src/Action/Type/ModalActionType.php | 8 +++++--- src/Resources/views/themes/base.html.twig | 2 +- src/Resources/views/themes/bootstrap_5.html.twig | 7 ++++++- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/assets/controllers/batch.js b/assets/controllers/batch.js index 0336964e..d31a5fc9 100755 --- a/assets/controllers/batch.js +++ b/assets/controllers/batch.js @@ -90,10 +90,15 @@ export default class extends Controller { #updateIdentifierHolderHref(identifierHolder, identifierMap) { let href; + let hrefHolder = 'href'; + + if (identifierHolder.dataset.hrefHolder !== undefined) { + hrefHolder = identifierHolder.dataset.hrefHolder; + } try { - href = new URL(identifierHolder.href); - } catch (exception) { + href = new URL(identifierHolder.dataset[hrefHolder]); + } catch (exception) {console.log(exception) return; } @@ -111,7 +116,7 @@ export default class extends Controller { } } - identifierHolder.href = href.toString(); + identifierHolder.dataset[hrefHolder] = href.toString(); } #updateIdentifierHolderDataParam(identifierHolder, identifierMap) { diff --git a/assets/package.json b/assets/package.json index ff580e13..a8a8d2cc 100755 --- a/assets/package.json +++ b/assets/package.json @@ -23,7 +23,7 @@ "bootstrap-modal": { "main": "controllers/bootstrap/modal.js", "fetch": "eager", - "enabled": true + "enabled": false } }, "importmap": { diff --git a/src/Action/Type/ModalActionType.php b/src/Action/Type/ModalActionType.php index 1fdd053c..5112d021 100755 --- a/src/Action/Type/ModalActionType.php +++ b/src/Action/Type/ModalActionType.php @@ -40,7 +40,7 @@ public function buildView(ActionView $view, ActionInterface $action, array $opti } } - $href = $options['href'] ?? $this->router->generate($options['route'], $options['route_params']); + $href = $options['href'] ?? $this->router->generate($options['route'], $options['route_params'], RouterInterface::ABSOLUTE_URL); $view->vars = array_replace($view->vars, [ 'href' => $href, @@ -51,7 +51,8 @@ public function configureOptions(OptionsResolver $resolver): void { $resolver ->define('route') - ->allowedTypes('string', 'callable') + ->default(null) + ->allowedTypes('null', 'string', 'callable') ; $resolver @@ -62,7 +63,8 @@ public function configureOptions(OptionsResolver $resolver): void $resolver ->define('href') - ->allowedTypes('string', 'callable') + ->default(null) + ->allowedTypes('null', 'string', 'callable') ; } } diff --git a/src/Resources/views/themes/base.html.twig b/src/Resources/views/themes/base.html.twig index b574e748..e363c96d 100755 --- a/src/Resources/views/themes/base.html.twig +++ b/src/Resources/views/themes/base.html.twig @@ -633,7 +633,7 @@ {% endblock %} {% block action_modal_control %} - {% set attr = { dataUrl }|filter(v => v != null)|merge(attr|default({})) %} + {% set attr = { href }|filter(v => v != null)|merge(attr|default({})) %} {% if batch %} {% set attr = { 'data-kreyu--data-table-bundle--batch-target': 'identifierHolder' }|merge(attr) %} diff --git a/src/Resources/views/themes/bootstrap_5.html.twig b/src/Resources/views/themes/bootstrap_5.html.twig index 2c0359a8..e487d223 100755 --- a/src/Resources/views/themes/bootstrap_5.html.twig +++ b/src/Resources/views/themes/bootstrap_5.html.twig @@ -727,7 +727,12 @@ {% block action_modal_control %}
{% set modalId = 'modalId-' ~ random() %}