Skip to content
Open
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
16 changes: 16 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 Down Expand Up @@ -79,6 +82,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 +127,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;

class BookType extends AbstractType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class BookType extends AbstractType
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;
}
}
7 changes: 4 additions & 3 deletions config/packages/sylius_resource.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ sylius_resource:

# Configure your resources
resources:
#app.book:
#classes:
#model: App\Entity\Book
app.book:
classes:
model: App\Entity\Book
form: App\Form\BookType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need this, configure it on your Resource metadata.

13 changes: 10 additions & 3 deletions config/reference.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
* only_exceptions?: bool|Param, // Default: false
* only_main_requests?: bool|Param, // Default: false
* dsn?: scalar|Param|null, // Default: "file:%kernel.cache_dir%/profiler"
* collect_serializer_data?: true|Param, // Default: true
* collect_serializer_data?: bool|Param, // Enables the serializer data collector and profiler panel. // Default: false
* },
* workflows?: bool|array{
* enabled?: bool|Param, // Default: false
Expand Down Expand Up @@ -255,6 +255,8 @@
* gc_maxlifetime?: scalar|Param|null,
* save_path?: scalar|Param|null, // Defaults to "%kernel.cache_dir%/sessions" if the "handler_id" option is not null.
* metadata_update_threshold?: int|Param, // Seconds to wait between 2 session metadata updates. // Default: 0
* sid_length?: int|Param, // Deprecated: Setting the "framework.session.sid_length.sid_length" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option.
* sid_bits_per_character?: int|Param, // Deprecated: Setting the "framework.session.sid_bits_per_character.sid_bits_per_character" configuration option is deprecated. It will be removed in version 8.0. No alternative is provided as PHP 8.4 has deprecated the related option.
* },
* request?: bool|array{ // Request configuration
* enabled?: bool|Param, // Default: false
Expand Down Expand Up @@ -328,10 +330,11 @@
* },
* validation?: bool|array{ // Validation configuration
* enabled?: bool|Param, // Default: true
* cache?: scalar|Param|null, // Deprecated: Setting the "framework.validation.cache.cache" configuration option is deprecated. It will be removed in version 8.0.
* enable_attributes?: bool|Param, // Default: true
* static_method?: list<scalar|Param|null>,
* translation_domain?: scalar|Param|null, // Default: "validators"
* email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|Param, // Default: "html5"
* email_validation_mode?: "html5"|"html5-allow-no-tld"|"strict"|"loose"|Param, // Default: "html5"
* mapping?: array{
* paths?: list<scalar|Param|null>,
* },
Expand All @@ -344,6 +347,9 @@
* services?: list<scalar|Param|null>,
* }>,
* },
* annotations?: bool|array{
* enabled?: bool|Param, // Default: false
* },
* serializer?: bool|array{ // Serializer configuration
* enabled?: bool|Param, // Default: false
* enable_attributes?: bool|Param, // Default: true
Expand Down Expand Up @@ -375,7 +381,7 @@
* },
* property_info?: bool|array{ // Property info configuration
* enabled?: bool|Param, // Default: true
* with_constructor_extractor?: bool|Param, // Registers the constructor extractor. // Default: true
* with_constructor_extractor?: bool|Param, // Registers the constructor extractor.
* },
* cache?: array{ // Cache configuration
* prefix_seed?: scalar|Param|null, // Used to namespace cache keys when using several apps with the same shared backend. // Default: "_%kernel.project_dir%.%kernel.container_class%"
Expand Down Expand Up @@ -1162,6 +1168,7 @@
* @psalm-type SecurityConfig = array{
* access_denied_url?: scalar|Param|null, // Default: null
* session_fixation_strategy?: "none"|"migrate"|"invalidate"|Param, // Default: "migrate"
* hide_user_not_found?: bool|Param, // Deprecated: The "hide_user_not_found" option is deprecated and will be removed in 8.0. Use the "expose_security_errors" option instead.
* expose_security_errors?: \Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::None|\Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::AccountStatus|\Symfony\Component\Security\Http\Authentication\ExposeSecurityLevel::All|Param, // Default: "none"
* erase_credentials?: bool|Param, // Default: true
* access_decision_manager?: array{
Expand Down
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
Loading