Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions app/Entity/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace App\Entity;

use App\Enum\BookCategory;
use App\Form\BookType;
use App\Grid\BookGrid;
use App\Repository\BookRepository;
use App\Responder\ExportGridToCsvResponder;
Expand All @@ -31,6 +33,7 @@
#[ORM\Entity(repositoryClass: BookRepository::class)]
#[AsResource(
section: 'admin',
formType: BookType::class,
templatesDir: '@SyliusAdminUi/crud',
routePrefix: '/admin',
operations: [
Expand All @@ -54,6 +57,7 @@
#[SyliusCrudRoutes(
alias: 'app.book',
path: '/admin/legacy/books',
form: BookType::class,
section: 'admin_legacy',
redirect: 'update',
templates: '@SyliusAdminUi/crud',
Expand All @@ -79,6 +83,9 @@ class Book implements ResourceInterface
#[NotBlank]
private ?string $authorName = null;

#[ORM\Column(type: 'enum', length: 255, nullable: true)]
private ?BookCategory $category = null;

#[ORM\Column(type: 'datetime_immutable')]
private \DateTimeImmutable $createdAt;

Expand Down Expand Up @@ -121,4 +128,14 @@ public function setCreatedAt(\DateTimeImmutable $createdAt): void
{
$this->createdAt = $createdAt;
}

public function getCategory(): ?BookCategory
{
return $this->category;
}

public function setCategory(?BookCategory $category): void
{
$this->category = $category;
}
}
42 changes: 42 additions & 0 deletions app/Enum/BookCategory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\Enum;

enum BookCategory: string
{
case FICTION = 'fiction';
case NON_FICTION = 'non-fiction';
case MYSTERY = 'mystery';
case THRILLER = 'thriller';
case SCIENCE_FICTION = 'science-fiction';
case FANTASY = 'fantasy';
case ROMANCE = 'romance';
case HORROR = 'horror';
case BIOGRAPHY = 'biography';
case HISTORY = 'history';
case SCIENCE = 'science';
case TECHNOLOGY = 'technology';
case BUSINESS = 'business';
case COOKING = 'cooking';
case TRAVEL = 'travel';
case POETRY = 'poetry';
case DRAMA = 'drama';
case CHILDREN = 'children';
case YOUNG_ADULT = 'young adult';
case RELIGION = 'religion';
case PHILOSOPHY = 'philosophy';
case ART = 'art';
case MANGA = 'manga';
case COMICS = 'comics';
}
7 changes: 7 additions & 0 deletions app/Factory/BookFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace App\Factory;

use App\Entity\Book;
use App\Enum\BookCategory;
use Zenstruck\Foundry\Persistence\PersistentObjectFactory;

/**
Expand All @@ -36,11 +37,17 @@ public function withAuthorName(string $authorName): self
return $this->with(['authorName' => $authorName]);
}

public function withCategory(BookCategory $category): self
{
return $this->with(['category' => $category]);
}

protected function defaults(): array|callable
{
return [
'title' => ucfirst(self::faker()->words(3, true)),
'authorName' => self::faker()->firstName() . ' ' . self::faker()->lastName(),
'category' => self::faker()->randomElement(BookCategory::cases()),
];
}
}
50 changes: 50 additions & 0 deletions app/Form/BookType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App\Form;

use App\Entity\Book;
use App\Enum\BookCategory;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EnumType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class BookType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('authorName')
->add('category', EnumType::class, [
'class' => BookCategory::class,
'choice_value' => fn (?BookCategory $enum) => $enum?->value,
'choice_label' => fn (BookCategory $choice) => ucfirst($choice->value),
'required' => false,
])
;
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Book::class,
]);
}

public function getBlockPrefix(): string
{
return 'sylius_resource';
}
}
36 changes: 19 additions & 17 deletions app/Grid/BookGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace App\Grid;

use App\Entity\Book;
use App\Enum\BookCategory;
use Sylius\Bundle\GridBundle\Builder\Action\Action;
use Sylius\Bundle\GridBundle\Builder\Action\CreateAction;
use Sylius\Bundle\GridBundle\Builder\Action\DeleteAction;
Expand All @@ -22,36 +23,42 @@
use Sylius\Bundle\GridBundle\Builder\ActionGroup\BulkActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\ItemActionGroup;
use Sylius\Bundle\GridBundle\Builder\ActionGroup\MainActionGroup;
use Sylius\Bundle\GridBundle\Builder\Field\EnumField;
use Sylius\Bundle\GridBundle\Builder\Field\StringField;
use Sylius\Bundle\GridBundle\Builder\Filter\EnumFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\StringFilter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Bundle\GridBundle\Grid\ResourceAwareGridInterface;
use Sylius\Component\Grid\Attribute\AsGrid;

final class BookGrid extends AbstractGrid implements ResourceAwareGridInterface
#[AsGrid(
resourceClass: Book::class,
name: 'app_book',
)]
final class BookGrid extends AbstractGrid
{
public static function getName(): string
{
return 'app_book';
}

public function buildGrid(GridBuilderInterface $gridBuilder): void
public function __invoke(GridBuilderInterface $gridBuilder): void
{
$gridBuilder
->orderBy('title')
->addFilter(
->withFilters(
StringFilter::create('search', ['title', 'authorName'])
->setLabel('sylius.ui.search'),
EnumFilter::create(name: 'category', enumClass: BookCategory::class, field: 'category')
->addFormOption('choice_value', fn (?BookCategory $enum) => $enum?->value)
->addFormOption('choice_label', fn (BookCategory $choice) => ucfirst($choice->value))
->setLabel('app.ui.category'),
)
->addField(
->withFields(
StringField::create('title')
->setLabel('app.ui.title')
->setSortable(true),
)
->addField(
StringField::create('authorName')
->setLabel('app.ui.author_name')
->setSortable(true),
EnumField::create('category')
->setLabel('app.ui.category')
->setSortable(true),
)
->addActionGroup(
MainActionGroup::create(
Expand All @@ -78,9 +85,4 @@ public function buildGrid(GridBuilderInterface $gridBuilder): void
)
;
}

public function getResourceClass(): string
{
return Book::class;
}
}
1 change: 1 addition & 0 deletions src/BootstrapAdminUi/config/app/grid/templates.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'exists' => '@SyliusBootstrapAdminUi/shared/grid/filter/exists.html.twig',
'select' => '@SyliusBootstrapAdminUi/shared/grid/filter/select.html.twig',
'string' => '@SyliusBootstrapAdminUi/shared/grid/filter/string.html.twig',
'enum' => '@SyliusBootstrapAdminUi/shared/grid/filter/enum.html.twig',
],
],
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% form_theme form '@SyliusBootstrapAdminUi/shared/form_theme.html.twig' %}

{{ form_row(form, { 'label': filter.label}) }}
4 changes: 2 additions & 2 deletions templates/book/show/content/page_body.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<div class="container-xl">
<div class="card mb-3">
<div class="card-body" {{ sylius_test_html_attribute('author-name') }}>
<strong>{{ 'app.ui.author'|trans }}:</strong>
{{ book.authorName }}
<p><strong>{{ 'app.ui.author'|trans }}:</strong> {{ book.authorName }}</p>
<p><strong>{{ 'app.ui.category'|trans }}:</strong>{{ book.category.value }}</p>
</div>
</div>
</div>
Expand Down
6 changes: 6 additions & 0 deletions tests/Functional/BookTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace MainTests\Sylius\Functional;

use App\Entity\Book;
use App\Enum\BookCategory;
use App\Factory\BookFactory;
use App\Factory\UserFactory;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
Expand Down Expand Up @@ -56,12 +57,14 @@ public function testBrowsingBooks(): void
BookFactory::new()
->withTitle('The Shining')
->withAuthorName('Stephen King')
->withCategory(BookCategory::HORROR)
->create()
;

BookFactory::new()
->withTitle('Carrie')
->withAuthorName('Stephen King')
->withCategory(BookCategory::HORROR)
->create()
;

Expand All @@ -79,17 +82,20 @@ public function testBrowsingBooks(): void
// Validate Table header
$this->assertSelectorTextContains('.sylius-table-column-title', 'Title');
$this->assertSelectorTextContains('.sylius-table-column-authorName', 'Author name');
$this->assertSelectorTextContains('.sylius-table-column-category', 'Category');
$this->assertSelectorTextContains('.sylius-table-column-actions', 'Actions');

// Validate Table data
$this->assertSelectorTextContains('tr.item:first-child', 'Carrie');
$this->assertSelectorTextContains('tr.item:first-child', 'Stephen King');
$this->assertSelectorTextContains('tr.item:first-child', 'horror');
$this->assertSelectorExists('tr.item:first-child [data-bs-title=Show]');
$this->assertSelectorExists('tr.item:first-child [data-bs-title=Edit]');
$this->assertSelectorExists('tr.item:first-child [data-bs-title=Delete]');

$this->assertSelectorTextContains('tr.item:last-child', 'The Shining');
$this->assertSelectorTextContains('tr.item:last-child', 'Stephen King');
$this->assertSelectorTextContains('tr.item:last-child', 'horror');
$this->assertSelectorExists('tr.item:last-child [data-bs-title=Show]');
$this->assertSelectorExists('tr.item:last-child [data-bs-title=Edit]');
$this->assertSelectorExists('tr.item:last-child [data-bs-title=Delete]');
Expand Down
1 change: 1 addition & 0 deletions translations/messages.de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ app:
book: Buch
books: Bücher
browsing_speakers: Referenten durchsuchen
category: Kategorie
company_name: Firmenname
conference: Konferenz
conferences: Konferenzen
Expand Down
1 change: 1 addition & 0 deletions translations/messages.de_AT.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ app:
book: Buch
books: Bücher
browsing_speakers: Referenten durchsuchen
category: Kategorie
company_name: Firmenname
conference: Konferenz
conferences: Konferenzen
Expand Down
1 change: 1 addition & 0 deletions translations/messages.de_CH.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ app:
book: Buch
books: Bücher
browsing_speakers: Referenten durchsuchen
category: Kategorie
company_name: Firmenname
conference: Konferenz
conferences: Konferenzen
Expand Down
1 change: 1 addition & 0 deletions translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ app:
book: Book
books: Books
browsing_speakers: Browsing speakers
category: Category
company_name: Company name
conference: Conference
conferences: Conferences
Expand Down
1 change: 1 addition & 0 deletions translations/messages.fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ app:
book: Livre
books: Livres
browsing_speakers: Parcourir les Conférencier-e-s
category: Catégorie
company_name: Société
conference: Conférence
conferences: Conférences
Expand Down