From f279be896efc90949ae9d350f49dc766c914a6fc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Thu, 6 Mar 2025 16:58:25 +0100 Subject: [PATCH 1/5] storybook: add Book and Review entities --- api/migrations/Version20250306152729.php | 37 +++++++++++++++ api/src/Entity/Book.php | 58 ++++++++++++++++++++++++ api/src/Entity/Review.php | 49 ++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 api/migrations/Version20250306152729.php create mode 100644 api/src/Entity/Book.php create mode 100644 api/src/Entity/Review.php diff --git a/api/migrations/Version20250306152729.php b/api/migrations/Version20250306152729.php new file mode 100644 index 00000000..fd915fce --- /dev/null +++ b/api/migrations/Version20250306152729.php @@ -0,0 +1,37 @@ +addSql('CREATE TABLE book (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, isbn VARCHAR(255) DEFAULT NULL, title VARCHAR(255) NOT NULL, description TEXT NOT NULL, author VARCHAR(255) NOT NULL, publication_date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE review (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, rating SMALLINT NOT NULL, body TEXT NOT NULL, author VARCHAR(255) NOT NULL, publication_date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, book_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_794381C616A2B381 ON review (book_id)'); + $this->addSql('ALTER TABLE review ADD CONSTRAINT FK_794381C616A2B381 FOREIGN KEY (book_id) REFERENCES book (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE review DROP CONSTRAINT FK_794381C616A2B381'); + $this->addSql('DROP TABLE book'); + $this->addSql('DROP TABLE review'); + } +} diff --git a/api/src/Entity/Book.php b/api/src/Entity/Book.php new file mode 100644 index 00000000..22191ed6 --- /dev/null +++ b/api/src/Entity/Book.php @@ -0,0 +1,58 @@ +reviews = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } +} diff --git a/api/src/Entity/Review.php b/api/src/Entity/Review.php new file mode 100644 index 00000000..3f716dc1 --- /dev/null +++ b/api/src/Entity/Review.php @@ -0,0 +1,49 @@ +id; + } +} From de512e90c4816981bd27c301aa4e06b3ef611168 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Thu, 6 Mar 2025 17:12:17 +0100 Subject: [PATCH 2/5] storybook: improve entities attributes --- api/src/Entity/Book.php | 21 ++++++++++++++++++++- api/src/Entity/Review.php | 22 +++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/api/src/Entity/Book.php b/api/src/Entity/Book.php index 22191ed6..e51d68a8 100644 --- a/api/src/Entity/Book.php +++ b/api/src/Entity/Book.php @@ -3,13 +3,31 @@ namespace App\Entity; use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\ApiProperty; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; use Doctrine\Common\Collections\ArrayCollection; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; -#[ApiResource] +#[ApiResource(mercure: true)] #[ORM\Entity] +#[ApiFilter(OrderFilter::class, properties: [ + 'id' => 'ASC', + 'isbn' => 'ASC', + 'title' => 'ASC', + 'author' => 'ASC', + 'publicationDate' => 'DESC' +])] +#[ApiFilter(SearchFilter::class, properties: [ + 'id' => 'exact', + 'title' => 'ipartial', + 'author' => 'ipartial' +])] +#[ApiFilter(DateFilter::class, properties: ['publicationDate'])] class Book { /** The ID of this book */ @@ -25,6 +43,7 @@ class Book /** The title of this book */ #[ORM\Column] #[Assert\NotBlank] + #[ApiProperty(iris: ['http://schema.org/name'])] public string $title = ''; /** The description of this book */ diff --git a/api/src/Entity/Review.php b/api/src/Entity/Review.php index 3f716dc1..dc7de3f2 100644 --- a/api/src/Entity/Review.php +++ b/api/src/Entity/Review.php @@ -3,12 +3,31 @@ namespace App\Entity; use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\ApiProperty; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Doctrine\Orm\Filter\DateFilter; +use ApiPlatform\Doctrine\Orm\Filter\NumericFilter; +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; -#[ApiResource] +#[ApiResource(mercure: true)] #[ORM\Entity] +#[ApiFilter(OrderFilter::class, properties: [ + 'id' => 'ASC', + 'rating' => 'ASC', + 'author' => 'ASC', + 'publicationDate' => 'DESC' +])] +#[ApiFilter(SearchFilter::class, properties: [ + 'id' => 'exact', + 'body' => 'ipartial', + 'author' => 'ipartial' +])] +#[ApiFilter(NumericFilter::class, properties: ['rating'])] +#[ApiFilter(DateFilter::class, properties: ['publicationDate'])] class Review { /** The ID of this review */ @@ -35,6 +54,7 @@ class Review /** The publication date of this review */ #[ORM\Column] #[Assert\NotNull] + #[ApiProperty(iris: ['http://schema.org/name'])] public ?\DateTimeImmutable $publicationDate = null; /** The book this review is about */ From 5182f885986a065bd1008f39e39e540760900b01 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Thu, 6 Mar 2025 17:28:14 +0100 Subject: [PATCH 3/5] storybook: add story using Field and Input Guessers --- src/stories/Custom.stories.tsx | 53 --------- src/stories/custom/UsingGuessers.stories.tsx | 115 +++++++++++++++++++ 2 files changed, 115 insertions(+), 53 deletions(-) delete mode 100644 src/stories/Custom.stories.tsx create mode 100644 src/stories/custom/UsingGuessers.stories.tsx diff --git a/src/stories/Custom.stories.tsx b/src/stories/Custom.stories.tsx deleted file mode 100644 index a68b6281..00000000 --- a/src/stories/Custom.stories.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import { HydraAdmin } from '../hydra'; -import ResourceGuesser from '../core/ResourceGuesser'; -import ListGuesser from '../list/ListGuesser'; -import ShowGuesser from '../show/ShowGuesser'; -import FieldGuesser from '../field/FieldGuesser'; -import EditGuesser from '../edit/EditGuesser'; -import InputGuesser from '../input/InputGuesser'; -import CreateGuesser from '../create/CreateGuesser'; - -export default { - title: 'Admin/Custom', - parameters: { - layout: 'fullscreen', - }, -}; - -const GreetingList = () => ( - - - -); - -const GreetingShow = () => ( - - - -); - -const GreetingEdit = () => ( - - - -); - -const GreetingCreate = () => ( - - - -); - -export const Custom = () => ( - - - -); diff --git a/src/stories/custom/UsingGuessers.stories.tsx b/src/stories/custom/UsingGuessers.stories.tsx new file mode 100644 index 00000000..15f8e57b --- /dev/null +++ b/src/stories/custom/UsingGuessers.stories.tsx @@ -0,0 +1,115 @@ +import React from 'react'; +import { HydraAdmin } from '../../hydra'; +import ResourceGuesser from '../../core/ResourceGuesser'; +import ListGuesser from '../../list/ListGuesser'; +import ShowGuesser from '../../show/ShowGuesser'; +import FieldGuesser from '../../field/FieldGuesser'; +import EditGuesser from '../../edit/EditGuesser'; +import InputGuesser from '../../input/InputGuesser'; +import CreateGuesser from '../../create/CreateGuesser'; + +export default { + title: 'Admin/Custom/UsingGuessers', + parameters: { + layout: 'fullscreen', + }, +}; + +const BookCreate = () => ( + + + + + + + +); + +const BookEdit = () => ( + + + + + + + +); + +const BookShow = () => ( + + + + + + + + +); + +const BookList = () => ( + + + + + + + +); + +const ReviewCreate = () => ( + + + + + + + +); + +const ReviewEdit = () => ( + + + + + + + +); + +const ReviewShow = () => ( + + + + + + + +); + +const ReviewList = () => ( + + + + + + +); + +export const UsingGuessers = () => ( + + + + +); From 9e367789c2933d91edcfc08ad5d2ae7acec91ddd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Thu, 6 Mar 2025 18:20:40 +0100 Subject: [PATCH 4/5] storybook: add Advanced Customization story --- .../custom/AdvancedCustomization.stories.tsx | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 src/stories/custom/AdvancedCustomization.stories.tsx diff --git a/src/stories/custom/AdvancedCustomization.stories.tsx b/src/stories/custom/AdvancedCustomization.stories.tsx new file mode 100644 index 00000000..c3c90b84 --- /dev/null +++ b/src/stories/custom/AdvancedCustomization.stories.tsx @@ -0,0 +1,247 @@ +import AutoStoriesIcon from '@mui/icons-material/AutoStories'; +import ReviewsIcon from '@mui/icons-material/Reviews'; +import { Rating, Stack } from '@mui/material'; +import React from 'react'; +import type { InputProps } from 'react-admin'; +import { + AutocompleteInput, + Create, + Datagrid, + DateField, + Edit, + Labeled, + Layout, + List, + NumberField, + ReferenceArrayField, + ReferenceField, + ReferenceInput, + Show, + SimpleForm, + SimpleList, + SimpleShowLayout, + TabbedShowLayout, + TextField, + TextInput, + WithRecord, + WrapperField, + defaultDarkTheme, + defaultLightTheme, + required, + useInput, +} from 'react-admin'; +import ResourceGuesser from '../../core/ResourceGuesser'; +import FieldGuesser from '../../field/FieldGuesser'; +import { HydraAdmin } from '../../hydra'; +import InputGuesser from '../../input/InputGuesser'; + +export default { + title: 'Admin/Custom/AdvancedCustomization', + parameters: { + layout: 'fullscreen', + }, +}; + +const BookCreate = () => ( + + + + + + + + + + + +); + +const BookEdit = () => ( + + + + + + + + + + + +); + +const BookShow = () => ( + + + + + + + + + + + + + + + review.author + .split(' ') + .map((name: string) => name[0]) + .join('') + } + // eslint-disable-next-line react/no-unstable-nested-components + tertiaryText={(review) => ( + + )} + /> + + + + +); + +const BookList = () => ( + + + + + + + + + +); + +const RatingInput = (props: InputProps) => { + const { field } = useInput(props); + return ( + { + field.onChange(value); + }} + /> + ); +}; + +const filterToBookQuery = (searchText: string) => ({ + title: `%${searchText}%`, +}); + +const ReviewCreate = () => ( + + + + + + + + + + + + +); + +const ReviewEdit = () => ( + + + + + + + + + + + + + + + +); + +const ReviewShow = () => ( + + + + + + + ( + + )} + /> + + + + +); + +const ReviewList = () => ( + + + + + + ( + + )} + /> + + + + +); + +export const AdvancedCustomization = () => ( + + + + +); From 24143de865cf28f0c366d93744605b36ec82a9c3 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Kaiser Date: Mon, 10 Mar 2025 16:03:14 +0100 Subject: [PATCH 5/5] storybook: add custom menu icons to the guessers story --- src/stories/custom/UsingGuessers.stories.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stories/custom/UsingGuessers.stories.tsx b/src/stories/custom/UsingGuessers.stories.tsx index 15f8e57b..79a59bee 100644 --- a/src/stories/custom/UsingGuessers.stories.tsx +++ b/src/stories/custom/UsingGuessers.stories.tsx @@ -1,3 +1,5 @@ +import AutoStoriesIcon from '@mui/icons-material/AutoStories'; +import ReviewsIcon from '@mui/icons-material/Reviews'; import React from 'react'; import { HydraAdmin } from '../../hydra'; import ResourceGuesser from '../../core/ResourceGuesser'; @@ -103,6 +105,7 @@ export const UsingGuessers = () => ( show={BookShow} edit={BookEdit} create={BookCreate} + icon={AutoStoriesIcon} /> ( show={ReviewShow} edit={ReviewEdit} create={ReviewCreate} + icon={ReviewsIcon} /> ); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy