Skip to content

Commit 6e14d4a

Browse files
committed
minor #3078 [App/E2E] Add examples listing on homepage, improve example page (Kocal)
This PR was merged into the 2.x branch. Discussion ---------- [App/E2E] Add examples listing on homepage, improve example page | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Docs? | no <!-- required for new features --> | Issues | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT <!-- Replace this notice by a description of your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - For new features, provide some code snippets to help understand usage. - Features and deprecations must be submitted against branch main. - Update/add documentation as required (we can help!) - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> Some micro visual improvements on the E2E app: <img width="1912" height="1237" alt="Capture d’écran 2025-09-12 à 14 48 34" src="https://github.com/user-attachments/assets/8a2995e9-0214-4923-927e-ad5f28e6271b" /> <img width="1912" height="1237" alt="Capture d’écran 2025-09-12 à 14 49 28" src="https://github.com/user-attachments/assets/e12173c6-7e7e-4415-924a-fc7c8f710129" /> Commits ------- c18daaa [App/E2E] Add examples listing on homepage, improve example page
2 parents 3daf951 + c18daaa commit 6e14d4a

File tree

27 files changed

+335
-88
lines changed

27 files changed

+335
-88
lines changed

apps/e2e/src/Controller/AutocompleteController.php

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,56 +12,4 @@
1212
#[Route('/ux-autocomplete')]
1313
final class AutocompleteController extends AbstractController
1414
{
15-
public function __construct(private readonly LoggerInterface $logger)
16-
{
17-
}
18-
19-
#[Route('/without-options')]
20-
public function withoutOptions(ChartBuilderInterface $chartBuilder): Response
21-
{
22-
$this->logger->critical('qsd');
23-
$chart = $chartBuilder->createChart(Chart::TYPE_LINE);
24-
25-
$chart->setData([
26-
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
27-
'datasets' => [
28-
[
29-
'label' => 'My First dataset',
30-
'backgroundColor' => 'rgb(255, 99, 132)',
31-
'borderColor' => 'rgb(255, 99, 132)',
32-
'data' => [0, 10, 5, 2, 20, 30, 45],
33-
],
34-
],
35-
]);
36-
37-
return $this->render('ux_autocomplete/index.html.twig', [
38-
'chart' => $chart,
39-
]);
40-
}
41-
42-
#[Route('/with-options')]
43-
public function withOptions(ChartBuilderInterface $chartBuilder): Response
44-
{
45-
$chart = $chartBuilder->createChart(Chart::TYPE_LINE);
46-
47-
$chart->setData([
48-
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
49-
'datasets' => [
50-
[
51-
'label' => 'My First dataset',
52-
'backgroundColor' => 'rgb(255, 99, 132)',
53-
'borderColor' => 'rgb(255, 99, 132)',
54-
'data' => [0, 10, 5, 2, 20, 30, 45],
55-
],
56-
],
57-
]);
58-
59-
$chart->setOptions([
60-
'showLines' => false,
61-
]);
62-
63-
return $this->render('ux_autocomplete/index.html.twig', [
64-
'chart' => $chart,
65-
]);
66-
}
6715
}

apps/e2e/src/Controller/ChartjsController.php

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,57 @@
55
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
66
use Symfony\Component\HttpFoundation\Response;
77
use Symfony\Component\Routing\Attribute\Route;
8+
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
9+
use Symfony\UX\Chartjs\Model\Chart;
810

911
#[Route('/ux-chartjs')]
1012
final class ChartjsController extends AbstractController
1113
{
12-
#[Route('/')]
13-
public function index(): Response
14+
#[Route('/without-options')]
15+
public function withoutOptions(ChartBuilderInterface $chartBuilder): Response
1416
{
17+
$chart = $chartBuilder->createChart(Chart::TYPE_LINE);
18+
19+
$chart->setData([
20+
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
21+
'datasets' => [
22+
[
23+
'label' => 'My First dataset',
24+
'backgroundColor' => 'rgb(255, 99, 132)',
25+
'borderColor' => 'rgb(255, 99, 132)',
26+
'data' => [0, 10, 5, 2, 20, 30, 45],
27+
],
28+
],
29+
]);
30+
31+
return $this->render('ux_chartjs/index.html.twig', [
32+
'chart' => $chart,
33+
]);
34+
}
35+
36+
#[Route('/with-options')]
37+
public function withOptions(ChartBuilderInterface $chartBuilder): Response
38+
{
39+
$chart = $chartBuilder->createChart(Chart::TYPE_LINE);
40+
41+
$chart->setData([
42+
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
43+
'datasets' => [
44+
[
45+
'label' => 'My First dataset',
46+
'backgroundColor' => 'rgb(255, 99, 132)',
47+
'borderColor' => 'rgb(255, 99, 132)',
48+
'data' => [0, 10, 5, 2, 20, 30, 45],
49+
],
50+
],
51+
]);
52+
53+
$chart->setOptions([
54+
'showLines' => false,
55+
]);
56+
1557
return $this->render('ux_chartjs/index.html.twig', [
16-
'controller_name' => 'ChartjsController',
58+
'chart' => $chart,
1759
]);
1860
}
1961
}

apps/e2e/src/Controller/HomeController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
namespace App\Controller;
44

5+
use App\Repository\ExampleRepository;
56
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
67
use Symfony\Component\HttpFoundation\Response;
78
use Symfony\Component\Routing\Attribute\Route;
89

910
final class HomeController extends AbstractController
1011
{
1112
#[Route('/', name: 'app_home')]
12-
public function index(): Response
13+
public function index(ExampleRepository $exampleRepository): Response
1314
{
14-
return $this->render('home.html.twig');
15+
return $this->render('home.html.twig', [
16+
'examples_by_package' => $exampleRepository->findAllByPackage(),
17+
]);
1518
}
1619
}

apps/e2e/src/Controller/MapController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public function withPolygons(#[MapQueryParameter] MapRenderer $renderer): Respon
143143
new Point(48.856613, 2.352222), // Paris
144144
],
145145
],
146-
infoWindow: new InfoWindow(content: 'A weird shape on the France'),
146+
infoWindow: new InfoWindow(content: 'A weird shape on France'),
147147
))
148148

149149
->addPolygon(new Polygon(
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace App\EventListener;
13+
14+
use App\Repository\ExampleRepository;
15+
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
16+
use Symfony\Component\HttpKernel\Event\RequestEvent;
17+
18+
#[AsEventListener]
19+
class ResolveExampleForUrlListener
20+
{
21+
public function __construct(
22+
private ExampleRepository $exampleRepository
23+
)
24+
{
25+
}
26+
27+
public function __invoke(RequestEvent $event): void
28+
{
29+
if (!$event->isMainRequest()) {
30+
return;
31+
}
32+
33+
$example = $this->exampleRepository->findOneByUrl($event->getRequest()->getRequestUri());
34+
$event->getRequest()->attributes->set('_example', $example);
35+
}
36+
}

apps/e2e/src/Example.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace App;
13+
14+
final readonly class Example
15+
{
16+
public function __construct(
17+
public UxPackage $uxPackage,
18+
public string $name,
19+
public string $description,
20+
public string $url
21+
) {
22+
}
23+
}
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 Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace App\Repository;
13+
14+
use App\Example;
15+
use App\UxPackage;
16+
17+
class ExampleRepository
18+
{
19+
/**
20+
* @var list<Example>
21+
*/
22+
private array $examples;
23+
24+
public function __construct() {
25+
$this->examples = [
26+
new Example(UxPackage::Map, 'Basic map (Leaflet)', 'A basic map centered on Paris with zoom level 12', '/ux-map/basic?renderer=leaflet'),
27+
new Example(UxPackage::Map, 'Basic map (Google)', 'A basic map centered on Paris with zoom level 12', '/ux-map/basic?renderer=google'),
28+
new Example(UxPackage::Map, 'With markers, fit bounds (Leaflet)', 'A map with 2 markers, and the bounds are automatically adjusted to fit both markers', '/ux-map/with-markers-and-fit-bounds-to-markers?renderer=leaflet'),
29+
new Example(UxPackage::Map, 'With markers, fit bounds (Google)', 'A map with 2 markers, and the bounds are automatically adjusted to fit both markers', '/ux-map/with-markers-and-fit-bounds-to-markers?renderer=google'),
30+
new Example(UxPackage::Map, 'With markers, zoomed on Paris (Leaflet)', 'A map with 2 markers (Paris and Lyon), zoomed on Paris', '/ux-map/with-markers-and-zoomed-on-paris?renderer=leaflet'),
31+
new Example(UxPackage::Map, 'With markers, zoomed on Paris (Google)', 'A map with 2 markers (Paris and Lyon), zoomed on Paris', '/ux-map/with-markers-and-zoomed-on-paris?renderer=google'),
32+
new Example(UxPackage::Map, 'With markers and info windows (Leaflet)', 'A map with 2 markers (Paris and Lyon), each with an info window', '/ux-map/with-markers-and-info-windows?renderer=leaflet'),
33+
new Example(UxPackage::Map, 'With markers and info windows (Google)', 'A map with 2 markers (Paris and Lyon), each with an info window', '/ux-map/with-markers-and-info-windows?renderer=google'),
34+
new Example(UxPackage::Map, 'With custom icon markers (Leaflet)', 'A map with 3 markers (Paris, Lyon, Bordeaux), each with a custom icon', '/ux-map/with-markers-and-custom-icons?renderer=leaflet'),
35+
new Example(UxPackage::Map, 'With custom icon markers (Google)', 'A map with 3 markers (Paris, Lyon, Bordeaux), each with a custom icon', '/ux-map/with-markers-and-custom-icons?renderer=google'),
36+
new Example(UxPackage::Map, 'With polygons (Leaflet)', 'A map with two polygons, one that covers main cities in Italy, and one weird shape on France', '/ux-map/with-polygons?renderer=leaflet'),
37+
new Example(UxPackage::Map, 'With polygons (Google)', 'A map with two polygons, one that covers main cities in Italy, and one weird shape on France', '/ux-map/with-polygons?renderer=google'),
38+
new Example(UxPackage::Map, 'With polylines (Leaflet)', 'A map with two polylines: one through Paris/Lyon/Marseille/Bordeaux, and the other one through Rennes/Nantes/Tours', '/ux-map/with-polylines?renderer=leaflet'),
39+
new Example(UxPackage::Map, 'With polylines (Google)', 'A map with two polylines: one through Paris/Lyon/Marseille/Bordeaux, and the other one through Rennes/Nantes/Tours', '/ux-map/with-polylines?renderer=google'),
40+
new Example(UxPackage::Map, 'With circles (Leaflet)', 'A map with two circles: one centered on Paris, the other on Lyon', '/ux-map/with-circles?renderer=leaflet'),
41+
new Example(UxPackage::Map, 'With circles (Google)', 'A map with two circles: one centered on Paris, the other on Lyon', '/ux-map/with-circles?renderer=google'),
42+
new Example(UxPackage::Map, 'With rectangles (Leaflet)', 'A map with two rectangles: one from Paris to Lille, the other from Lyon to Bordeaux', '/ux-map/with-rectangles?renderer=leaflet'),
43+
new Example(UxPackage::Map, 'With rectangles (Google)', 'A map with two rectangles: one from Paris to Lille, the other from Lyon to Bordeaux', '/ux-map/with-rectangles?renderer=google'),
44+
new Example(UxPackage::React, 'Basic React Component', 'A basic React component that displays a welcoming message', '/ux-react/'),
45+
new Example(UxPackage::Svelte, 'Basic Svelte Component', 'A basic Svelte component that displays a welcoming message', '/ux-svelte/'),
46+
new Example(UxPackage::Vue, 'Basic Vue Component', 'A basic Vue component that displays a welcoming message', '/ux-vue/'),
47+
];
48+
}
49+
50+
/**
51+
* @return list<Example>
52+
*/
53+
public function findAll(): array
54+
{
55+
return $this->examples;
56+
}
57+
58+
public function findAllByPackage(): array
59+
{
60+
$grouped = [];
61+
62+
foreach ($this->examples as $example) {
63+
$grouped[$example->uxPackage->value][] = $example;
64+
}
65+
66+
return $grouped;
67+
}
68+
69+
public function findOneByUrl(string $url): ?Example
70+
{
71+
foreach ($this->examples as $example) {
72+
if ($example->url === $url) {
73+
return $example;
74+
}
75+
}
76+
77+
return null;
78+
}
79+
}

apps/e2e/src/UxPackage.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace App;
13+
14+
enum UxPackage: string
15+
{
16+
case Autocomplete = 'UX Autocomplete';
17+
case ChartJs = 'UX Chart';
18+
case Cropperjs = 'UX Cropperjs';
19+
case Icons = 'UX Icons';
20+
//case LazyImage = 'UX LazyImage'; // deprecated/removed
21+
case Map = 'UX Map';
22+
case Notify = 'UX Notify';
23+
case React = 'UX React';
24+
case StimulusBundle = 'UX StimulusBundle';
25+
case Svelte = 'UX Svelte';
26+
// case Swup; // deprecated/removed
27+
// case TogglePassword; // deprecated/removed
28+
// case Toolkit; // not subject to E2E
29+
case Translator = 'UX Translator';
30+
case Turbo = 'UX Turbo';
31+
case TwigComponent = 'UX TwigComponent';
32+
// case Typed; // deprecated
33+
case Vue = 'UX Vue';
34+
35+
public function getDocumentationUrl(): string
36+
{
37+
return match($this) {
38+
self::Autocomplete => 'https://ux.symfony.com/autocomplete',
39+
self::ChartJs => 'https://ux.symfony.com/chartjs',
40+
self::Cropperjs => 'https://ux.symfony.com/cropperjs',
41+
self::Icons => 'https://ux.symfony.com/icons',
42+
self::Map => 'https://ux.symfony.com/map',
43+
self::Notify => 'https://ux.symfony.com/notify',
44+
self::React => 'https://ux.symfony.com/react',
45+
self::StimulusBundle => 'https://ux.symfony.com/stimulus',
46+
self::Svelte => 'https://ux.symfony.com/svelte',
47+
self::Translator => 'https://ux.symfony.com/translator',
48+
self::Turbo => 'https://ux.symfony.com/turbo',
49+
self::TwigComponent => 'https://ux.symfony.com/twig-component',
50+
self::Vue => 'https://ux.symfony.com/vue',
51+
};
52+
}
53+
}

apps/e2e/templates/base.html.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
1717
<div class="container">
1818
<a class="navbar-brand" href="{{ path('app_home') }}">E2E App</a>
19+
{% block navbar_brand_after %}{% endblock %}
1920
</div>
2021
</nav>
2122

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{% extends 'base.html.twig' %}
2+
3+
{% set example = app.request.attributes.get('_example') %}
4+
5+
{% block title %}
6+
{{ example.uxPackage.value }}: {{ example.name }}
7+
{% endblock %}
8+
9+
{% block navbar_brand_after %}
10+
<div class="navbar-collapse">
11+
<span class="navbar-text">{{ example.uxPackage.value }}</span>
12+
</div>
13+
{% endblock %}
14+
15+
{% block main %}
16+
<div class="container mt-4">
17+
<h1>{{ example.name }}</h1>
18+
<p>{{ example.description }}</p>
19+
20+
{% block example %}{% endblock %}
21+
</div>
22+
{% endblock %}

0 commit comments

Comments
 (0)