Skip to content

Commit e1bf8b3

Browse files
committed
[PoC] Live component data-table
1 parent 8aa91f7 commit e1bf8b3

File tree

24 files changed

+628
-17
lines changed

24 files changed

+628
-17
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace App\Grid\Renderer;
15+
16+
use Sylius\Bundle\ResourceBundle\Grid\Parser\OptionsParserInterface;
17+
use Sylius\Component\Grid\Definition\Action;
18+
use Sylius\Component\Grid\Renderer\BulkActionGridRendererInterface;
19+
use Sylius\Component\Grid\View\GridViewInterface;
20+
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
21+
use Symfony\Component\DependencyInjection\Attribute\Autowire;
22+
use Symfony\Component\HttpFoundation\Request;
23+
use Symfony\Component\HttpFoundation\RequestStack;
24+
use Twig\Environment;
25+
26+
#[AsDecorator(decorates: 'sylius.custom_bulk_action_grid_renderer.twig')]
27+
final class TwigBulkActionGridRenderer implements BulkActionGridRendererInterface
28+
{
29+
public function __construct(
30+
private readonly Environment $twig,
31+
private readonly OptionsParserInterface $optionsParser,
32+
#[Autowire(param: 'sylius.grid.templates.bulk_action')]
33+
private array $bulkActionTemplates = [],
34+
private readonly RequestStack|null $requestStack = null,
35+
) {
36+
}
37+
38+
public function renderBulkAction(GridViewInterface $gridView, Action $bulkAction, $data = null): string
39+
{
40+
$type = $bulkAction->getType();
41+
if (!isset($this->bulkActionTemplates[$type])) {
42+
throw new \InvalidArgumentException(sprintf('Missing template for bulk action type "%s".', $type));
43+
}
44+
45+
$options = $this->optionsParser->parseOptions(
46+
$bulkAction->getOptions(),
47+
$this->requestStack?->getCurrentRequest() ?? new Request(),
48+
$data,
49+
);
50+
51+
return $this->twig->render($this->bulkActionTemplates[$type], [
52+
'grid' => $gridView,
53+
'action' => $bulkAction,
54+
'data' => $data,
55+
'options' => $options,
56+
]);
57+
}
58+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace App\Grid\Renderer;
15+
16+
use Sylius\Bundle\ResourceBundle\Grid\Parser\OptionsParserInterface;
17+
use Sylius\Component\Grid\Definition\Action;
18+
use Sylius\Component\Grid\Definition\Field;
19+
use Sylius\Component\Grid\Definition\Filter;
20+
use Sylius\Component\Grid\Renderer\GridRendererInterface;
21+
use Sylius\Component\Grid\View\GridViewInterface;
22+
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
23+
use Symfony\Component\DependencyInjection\Attribute\Autowire;
24+
use Symfony\Component\HttpFoundation\Request;
25+
use Symfony\Component\HttpFoundation\RequestStack;
26+
use Twig\Environment;
27+
28+
#[AsDecorator(decorates: 'sylius.custom_grid_renderer.twig')]
29+
final class TwigGridRenderer implements GridRendererInterface
30+
{
31+
public function __construct(
32+
private readonly GridRendererInterface $gridRenderer,
33+
private readonly Environment $twig,
34+
private readonly OptionsParserInterface $optionsParser,
35+
#[Autowire(param: 'sylius.grid.templates.action')]
36+
private array $actionTemplates = [],
37+
private readonly RequestStack|null $requestStack = null,
38+
) {
39+
}
40+
41+
public function render(GridViewInterface $gridView, string|null $template = null): string
42+
{
43+
return $this->gridRenderer->render($gridView, $template);
44+
}
45+
46+
public function renderField(GridViewInterface $gridView, Field $field, $data): string
47+
{
48+
return $this->gridRenderer->renderField($gridView, $field, $data);
49+
}
50+
51+
public function renderAction(GridViewInterface $gridView, Action $action, $data = null): string
52+
{
53+
$type = $action->getType();
54+
55+
$template = $action->getOptions()['template'] ?? $this->actionTemplates[$type] ?? null;
56+
57+
if (null === $template) {
58+
throw new \InvalidArgumentException(sprintf('Missing template for action type "%s".', $type));
59+
}
60+
61+
$options = $this->optionsParser->parseOptions(
62+
$action->getOptions(),
63+
$this->requestStack?->getCurrentRequest() ?? new Request(),
64+
$data,
65+
);
66+
67+
return $this->twig->render($template, [
68+
'grid' => $gridView,
69+
'action' => $action,
70+
'data' => $data,
71+
'options' => $options,
72+
]);
73+
}
74+
75+
public function renderFilter(GridViewInterface $gridView, Filter $filter): string
76+
{
77+
return $this->gridRenderer->renderFilter($gridView, $filter);
78+
}
79+
}

app/Grid/SpeakerGrid.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public static function getName(): string
3838
public function buildGrid(GridBuilderInterface $gridBuilder): void
3939
{
4040
$gridBuilder
41+
->setLimits([10, 25, 50])
4142
->addFilter(
4243
StringFilter::create('search', ['firstName', 'lastName', 'companyName'])
4344
->setLabel('sylius.ui.search'),
@@ -82,8 +83,23 @@ public function buildGrid(GridBuilderInterface $gridBuilder): void
8283
],
8384
],
8485
]),
85-
UpdateAction::create(),
86-
DeleteAction::create(),
86+
UpdateAction::create()
87+
->setOptions([
88+
'link' => [
89+
'route' => 'app_admin_speaker_update',
90+
'parameters' => [
91+
'id' => 'resource.id',
92+
],
93+
],
94+
]),
95+
DeleteAction::create()->setOptions([
96+
'link' => [
97+
'route' => 'app_admin_speaker_delete',
98+
'parameters' => [
99+
'id' => 'resource.id',
100+
],
101+
],
102+
]),
87103
),
88104
)
89105
->addActionGroup(
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace App\Twig\Component;
15+
16+
use App\Grid\SpeakerGrid;
17+
use Sylius\TwigComponentGrid\Twig\Component\ComponentWithDataTableTrait;
18+
use Sylius\TwigHooks\LiveComponent\HookableLiveComponentTrait;
19+
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
20+
use Symfony\UX\LiveComponent\DefaultActionTrait;
21+
22+
#[AsLiveComponent(
23+
name: 'admin_speaker_grid',
24+
template: '@SyliusBootstrapAdminUi/shared/components/grid/data_table.html.twig',
25+
route: 'sylius_admin_ui_live_component',
26+
)]
27+
class SpeakerDataTableComponent
28+
{
29+
use DefaultActionTrait;
30+
use HookableLiveComponentTrait;
31+
use ComponentWithDataTableTrait;
32+
33+
protected function getGrid(): string
34+
{
35+
return SpeakerGrid::class;
36+
}
37+
}

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
"psr-4": {
7373
"Sylius\\AdminUi\\": "src/AdminUi/src/",
7474
"Sylius\\BootstrapAdminUi\\": "src/BootstrapAdminUi/src/",
75+
"Sylius\\TwigComponentGrid\\": "src/TwigComponentGrid/src/",
7576
"Sylius\\TwigExtra\\": "src/TwigExtra/src/",
7677
"Sylius\\TwigHooks\\": "src/TwigHooks/src/",
7778
"Sylius\\UiTranslations\\": "src/UiTranslations/src/"
@@ -95,6 +96,7 @@
9596
"replace": {
9697
"sylius/admin-ui": "self.version",
9798
"sylius/bootstrap-admin-ui": "self.version",
99+
"sylius/twig-component-grid": "self.version",
98100
"sylius/twig-extra": "self.version",
99101
"sylius/twig-hooks": "self.version",
100102
"sylius/ui-translations": "self.version"
@@ -109,7 +111,7 @@
109111
},
110112
"extra": {
111113
"symfony": {
112-
"require": "7.1.*"
114+
"require": "7.2.*"
113115
}
114116
},
115117
"scripts": {

config/bundles.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
Sylius\AdminUi\Symfony\SyliusAdminUiBundle::class => ['all' => true],
1010
Sylius\UiTranslations\Symfony\SyliusUiTranslationsBundle::class => ['all' => true],
1111
Sylius\BootstrapAdminUi\Symfony\SyliusBootstrapAdminUiBundle::class => ['all' => true],
12+
Sylius\TwigComponentGrid\Symfony\SyliusTwigComponentGridBundle::class => ['all' => true],
1213
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
1314
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
1415
Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true],

config/sylius/twig_hooks/speaker/index.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1515

16+
use App\Twig\Component\SpeakerDataTableComponent;
17+
use App\Twig\Component\SpeakerGridComponent;
18+
1619
return static function (ContainerConfigurator $container): void {
1720
$container->extension('sylius_twig_hooks', [
1821
'hooks' => [
@@ -26,6 +29,18 @@
2629
],
2730
],
2831
],
32+
33+
'sylius_admin.speaker.index.content.grid' => [
34+
'data_table' => [
35+
'component' => SpeakerDataTableComponent::class,
36+
'props' => [
37+
'page' => '@=_context.page',
38+
'limit' => '@=_context.limit',
39+
'criteria' => '@=_context.criteria',
40+
'sorting' => '@=_context.sorting',
41+
],
42+
],
43+
],
2944
],
3045
]);
3146
};

importmap.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,12 @@
4545
'@symfony/ux-live-component' => [
4646
'path' => './vendor/symfony/ux-live-component/assets/dist/live_controller.js',
4747
],
48+
'tom-select/dist/css/tom-select.bootstrap4.css' => [
49+
'version' => '2.4.3',
50+
'type' => 'css',
51+
],
52+
'tom-select/dist/css/tom-select.bootstrap5.css' => [
53+
'version' => '2.4.3',
54+
'type' => 'css',
55+
],
4856
];

src/AdminUi/config/routes.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@
3232
'template' => '@SyliusAdminUi/dashboard/index.html.twig',
3333
])
3434
;
35+
36+
$routes->add('sylius_admin_ui_live_component', '/_components/{_live_component}/{_live_action}')
37+
->defaults([
38+
'_live_action' => 'get',
39+
])
40+
;
3541
};

src/BootstrapAdminUi/assets/styles/_body.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ a.link-reset {
4040
text-decoration: none;
4141
}
4242

43+
button.link-reset {
44+
border: none;
45+
background-color: transparent;
46+
text-transform: inherit;
47+
font-weight: inherit;
48+
}
49+
4350
.btn-collapse {
4451
&.collapsed {
4552
.icon-chevron-right {

0 commit comments

Comments
 (0)