diff --git a/.gitignore b/.gitignore
index 1c7a3e2..1472394 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,3 +69,5 @@ npm-debug.log
yarn-error.log
###< symfony/webpack-encore-bundle ###
+/public/book_covers/
+/public/book_files/
diff --git a/.idea/biblio.iml b/.idea/biblio.iml
index 2a364b1..274e040 100644
--- a/.idea/biblio.iml
+++ b/.idea/biblio.iml
@@ -62,7 +62,6 @@
-
@@ -105,6 +104,7 @@
+
diff --git a/.idea/php.xml b/.idea/php.xml
index 9d4c1f6..aece6a1 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -59,7 +59,6 @@
-
diff --git a/assets/app.js b/assets/app.js
deleted file mode 100644
index bb0a6aa..0000000
--- a/assets/app.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Welcome to your app's main JavaScript file!
- *
- * We recommend including the built version of this JavaScript file
- * (and its CSS file) in your base layout (base.html.twig).
- */
-
-// any CSS you import will output into a single css file (app.css in this case)
-import './styles/app.css';
-
-// start the Stimulus application
-import './bootstrap';
diff --git a/assets/bootstrap.js b/assets/bootstrap.js
deleted file mode 100644
index 4ab2df6..0000000
--- a/assets/bootstrap.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { startStimulusApp } from '@symfony/stimulus-bridge';
-
-// Registers Stimulus controllers from controllers.json and in the controllers/ directory
-export const app = startStimulusApp(require.context(
- '@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
- true,
- /\.[jt]sx?$/
-));
-
-// register any custom, 3rd party controllers here
-// app.register('some_controller_name', SomeImportedController);
diff --git a/assets/controllers.json b/assets/controllers.json
deleted file mode 100644
index a1c6e90..0000000
--- a/assets/controllers.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "controllers": [],
- "entrypoints": []
-}
diff --git a/assets/controllers/hello_controller.js b/assets/controllers/hello_controller.js
deleted file mode 100644
index e847027..0000000
--- a/assets/controllers/hello_controller.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Controller } from '@hotwired/stimulus';
-
-/*
- * This is an example Stimulus controller!
- *
- * Any element with a data-controller="hello" attribute will cause
- * this controller to be executed. The name "hello" comes from the filename:
- * hello_controller.js -> "hello"
- *
- * Delete this file or adapt it for your use!
- */
-export default class extends Controller {
- connect() {
- this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
- }
-}
diff --git a/assets/styles/app.css b/assets/styles/app.css
deleted file mode 100644
index cb33b13..0000000
--- a/assets/styles/app.css
+++ /dev/null
@@ -1,3 +0,0 @@
-body {
- background-color: lightgray;
-}
diff --git a/composer.json b/composer.json
index 55f86ec..5adcfc4 100644
--- a/composer.json
+++ b/composer.json
@@ -42,7 +42,6 @@
"symfony/validator": "6.0.*",
"symfony/web-link": "6.0.*",
"symfony/webapp-meta": "^1.0",
- "symfony/webpack-encore-bundle": "^1.12",
"symfony/yaml": "6.0.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12|^3.0"
diff --git a/composer.lock b/composer.lock
index b783e61..5166d09 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "9e2f5ddba7a9c27abf3decbe843a4160",
+ "content-hash": "bfe2f245934ec051aa999bacee2521d8",
"packages": [
{
"name": "doctrine/annotations",
@@ -7281,77 +7281,6 @@
],
"time": "2021-10-20T16:02:05+00:00"
},
- {
- "name": "symfony/webpack-encore-bundle",
- "version": "v1.14.1",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/webpack-encore-bundle.git",
- "reference": "6b18be99bf2a5a402b80a2c00043fe0b365fe836"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/webpack-encore-bundle/zipball/6b18be99bf2a5a402b80a2c00043fe0b365fe836",
- "reference": "6b18be99bf2a5a402b80a2c00043fe0b365fe836",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1.3",
- "symfony/asset": "^4.4 || ^5.0 || ^6.0",
- "symfony/config": "^4.4 || ^5.0 || ^6.0",
- "symfony/dependency-injection": "^4.4 || ^5.0 || ^6.0",
- "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0",
- "symfony/service-contracts": "^1.0 || ^2.0 || ^3.0"
- },
- "require-dev": {
- "symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0",
- "symfony/phpunit-bridge": "^5.3 || ^6.0",
- "symfony/twig-bundle": "^4.4 || ^5.0 || ^6.0",
- "symfony/web-link": "^4.4 || ^5.0 || ^6.0"
- },
- "type": "symfony-bundle",
- "extra": {
- "thanks": {
- "name": "symfony/webpack-encore",
- "url": "https://github.com/symfony/webpack-encore"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\WebpackEncoreBundle\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Integration with your Symfony app & Webpack Encore!",
- "support": {
- "issues": "https://github.com/symfony/webpack-encore-bundle/issues",
- "source": "https://github.com/symfony/webpack-encore-bundle/tree/v1.14.1"
- },
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2022-05-03T17:55:32+00:00"
- },
{
"name": "symfony/yaml",
"version": "v6.0.3",
diff --git a/config/bundles.php b/config/bundles.php
index de3979f..887a0e3 100644
--- a/config/bundles.php
+++ b/config/bundles.php
@@ -7,7 +7,6 @@ return [
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
- Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml
index f9f4cc5..50c5d7f 100644
--- a/config/packages/twig.yaml
+++ b/config/packages/twig.yaml
@@ -1,6 +1,6 @@
twig:
default_path: '%kernel.project_dir%/templates'
-
+ form_theme: 'bootstrap_5_layout.html.twig'
when@test:
twig:
strict_variables: true
diff --git a/config/packages/webpack_encore.yaml b/config/packages/webpack_encore.yaml
deleted file mode 100644
index 46834f0..0000000
--- a/config/packages/webpack_encore.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
-webpack_encore:
- # The path where Encore is building the assets - i.e. Encore.setOutputPath()
- output_path: '%kernel.project_dir%/public/build'
- # If multiple builds are defined (as shown below), you can disable the default build:
- # output_path: false
-
- # Set attributes that will be rendered on all script and link tags
- script_attributes:
- defer: true
- # Uncomment (also under link_attributes) if using Turbo Drive
- # https://turbo.hotwired.dev/handbook/drive#reloading-when-assets-change
- # 'data-turbo-track': reload
- # link_attributes:
- # Uncomment if using Turbo Drive
- # 'data-turbo-track': reload
-
- # If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials')
- # crossorigin: 'anonymous'
-
- # Preload all rendered script and link tags automatically via the HTTP/2 Link header
- # preload: true
-
- # Throw an exception if the entrypoints.json file is missing or an entry is missing from the data
- # strict_mode: false
-
- # If you have multiple builds:
- # builds:
- # pass "frontend" as the 3rg arg to the Twig functions
- # {{ encore_entry_script_tags('entry1', null, 'frontend') }}
-
- # frontend: '%kernel.project_dir%/public/frontend/build'
-
- # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
- # Put in config/packages/prod/webpack_encore.yaml
- # cache: true
-
-framework:
- assets:
- json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
-
-#when@prod:
-# webpack_encore:
-# # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
-# # Available in version 1.2
-# cache: true
-
-#when@test:
-# webpack_encore:
-# strict_mode: false
diff --git a/config/services.yaml b/config/services.yaml
index 2d6a76f..06bf8e4 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -4,6 +4,8 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
+ book_covers: '%kernel.project_dir%/public/book_covers/'
+ book_files: '%kernel.project_dir%/public/book_files/'
services:
# default configuration for services in *this* file
diff --git a/migrations/Version20220520082729.php b/migrations/Version20220520082729.php
new file mode 100644
index 0000000..27162c2
--- /dev/null
+++ b/migrations/Version20220520082729.php
@@ -0,0 +1,35 @@
+addSql('CREATE TABLE book (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, language VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, publisher VARCHAR(255) DEFAULT NULL, publish_date DATE DEFAULT NULL, filename VARCHAR(255) DEFAULT NULL, original_filename VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+ $this->addSql('CREATE TABLE `user` (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+ $this->addSql('CREATE TABLE messenger_messages (id BIGINT AUTO_INCREMENT NOT NULL, body LONGTEXT NOT NULL, headers LONGTEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at DATETIME NOT NULL, available_at DATETIME NOT NULL, delivered_at DATETIME DEFAULT NULL, INDEX IDX_75EA56E0FB7336F0 (queue_name), INDEX IDX_75EA56E0E3BD61CE (available_at), INDEX IDX_75EA56E016BA31DB (delivered_at), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql('DROP TABLE book');
+ $this->addSql('DROP TABLE `user`');
+ $this->addSql('DROP TABLE messenger_messages');
+ }
+}
diff --git a/migrations/Version20220520124026.php b/migrations/Version20220520124026.php
new file mode 100644
index 0000000..b03d66d
--- /dev/null
+++ b/migrations/Version20220520124026.php
@@ -0,0 +1,31 @@
+addSql('ALTER TABLE book ADD subtitle VARCHAR(255) DEFAULT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql('ALTER TABLE book DROP subtitle');
+ }
+}
diff --git a/package.json b/package.json
deleted file mode 100644
index e9d1380..0000000
--- a/package.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "devDependencies": {
- "@hotwired/stimulus": "^3.0.0",
- "@symfony/stimulus-bridge": "^3.0.0",
- "@symfony/webpack-encore": "^2.0.0",
- "core-js": "^3.0.0",
- "regenerator-runtime": "^0.13.2",
- "webpack-notifier": "^1.6.0"
- },
- "license": "UNLICENSED",
- "private": true,
- "scripts": {
- "dev-server": "encore dev-server",
- "dev": "encore dev",
- "watch": "encore dev --watch",
- "build": "encore production --progress"
- }
-}
diff --git a/src/Controller/BookController.php b/src/Controller/BookController.php
new file mode 100644
index 0000000..9b8f005
--- /dev/null
+++ b/src/Controller/BookController.php
@@ -0,0 +1,126 @@
+render('book/index.html.twig', [
+ 'books' => $bookRepository->findAll(),
+ ]);
+ }
+
+ #[Route('/new', name: 'app_book_new', methods: ['GET', 'POST'])]
+ public function new(Request $request, BookRepository $bookRepository): Response
+ {
+ $book = new Book();
+ $form = $this->createForm(BookType::class, $book);
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ $bookRepository->add($book, true);
+
+ $cover = $request->files->get('book')['cover'];
+ if ($cover) {
+ $cover->move(
+ $this->getParameter('book_covers'),
+ 'cover_' . $book->getId() . '.' . $cover->guessClientExtension()
+ );
+ }
+
+ $ebook = $request->files->get('book')['ebook'];
+ if ($ebook) {
+ $ebook->move(
+ $this->getParameter('book_files'),
+ 'ebook_' . $book->getId() . '.' . $ebook->guessClientExtension()
+ );
+ }
+
+ dd($book->getId());
+
+ return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ return $this->renderForm('book/new.html.twig', [
+ 'book' => $book,
+ 'form' => $form,
+ ]);
+ }
+
+ #[Route('/{id}', name: 'app_book_show', methods: ['GET'])]
+ public function show(Book $book): Response
+ {
+ return $this->render('book/show.html.twig', [
+ 'book' => $book,
+ ]);
+ }
+
+ #[Route('/{id}/edit', name: 'app_book_edit', methods: ['GET', 'POST'])]
+ public function edit(Request $request, Book $book, BookRepository $bookRepository): Response
+ {
+ $form = $this->createForm(BookType::class, $book);
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+ $cover = $request->files->get('book')['cover'];
+ if ($cover) {
+ $cover->move(
+ $this->getParameter('book_covers'),
+ 'cover_' . $book->getId() . '.jpg'
+ );
+ }
+
+ /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $ebook */
+ $ebook = $request->files->get('book')['ebook'];
+ if ($ebook) {
+ $ebook->move(
+ $this->getParameter('book_files'),
+ 'ebook_' . $book->getId() . '.' . $ebook->guessClientExtension()
+ );
+ }
+
+ $book->setOriginalFilename($ebook->getClientOriginalName());
+ $bookRepository->add($book, true);
+
+
+ return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ return $this->renderForm('book/edit.html.twig', [
+ 'book' => $book,
+ 'form' => $form,
+ ]);
+ }
+
+ #[Route('/{id}', name: 'app_book_delete', methods: ['POST'])]
+ public function delete(Request $request, Book $book, BookRepository $bookRepository): Response
+ {
+ if ($this->isCsrfTokenValid('delete' . $book->getId(), $request->request->get('_token'))) {
+ $bookRepository->remove($book, true);
+ }
+
+ return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
+ }
+
+ #[Route('/download/{id}', name: 'app_book_download', methods: ['GET'])]
+ public function downloadBook(Book $book): BinaryFileResponse
+ {
+ return $this->file(
+ $this->getParameter('book_files') . '/' . 'ebook_' . $book->getId() . '.'.pathinfo($book->getOriginalFilename(), PATHINFO_EXTENSION),
+ $book->getOriginalFilename()
+ );
+ }
+}
diff --git a/src/Entity/Book.php b/src/Entity/Book.php
new file mode 100644
index 0000000..b65a22b
--- /dev/null
+++ b/src/Entity/Book.php
@@ -0,0 +1,140 @@
+id;
+ }
+
+ public function getTitle(): ?string
+ {
+ return $this->Title;
+ }
+
+ public function setTitle(string $Title): self
+ {
+ $this->Title = $Title;
+
+ return $this;
+ }
+
+ public function getLanguage(): ?string
+ {
+ return $this->language;
+ }
+
+ public function setLanguage(string $language): self
+ {
+ $this->language = $language;
+
+ return $this;
+ }
+
+ public function getDescription(): ?string
+ {
+ return $this->description;
+ }
+
+ public function setDescription(?string $description): self
+ {
+ $this->description = $description;
+
+ return $this;
+ }
+
+ public function getPublisher(): ?string
+ {
+ return $this->publisher;
+ }
+
+ public function setPublisher(?string $publisher): self
+ {
+ $this->publisher = $publisher;
+
+ return $this;
+ }
+
+ public function getPublishDate(): ?\DateTimeInterface
+ {
+ return $this->publish_date;
+ }
+
+ public function setPublishDate(?\DateTimeInterface $publish_date): self
+ {
+ $this->publish_date = $publish_date;
+
+ return $this;
+ }
+
+ public function getFilename(): ?string
+ {
+ return $this->filename;
+ }
+
+ public function setFilename(?string $filename): self
+ {
+ $this->filename = $filename;
+
+ return $this;
+ }
+
+ public function getOriginalFilename(): ?string
+ {
+ return $this->original_filename;
+ }
+
+ public function setOriginalFilename(?string $original_filename): self
+ {
+ $this->original_filename = $original_filename;
+
+ return $this;
+ }
+
+ public function getSubtitle(): ?string
+ {
+ return $this->subtitle;
+ }
+
+ public function setSubtitle(?string $subtitle): self
+ {
+ $this->subtitle = $subtitle;
+
+ return $this;
+ }
+}
diff --git a/src/Form/BookType.php b/src/Form/BookType.php
new file mode 100644
index 0000000..1743edc
--- /dev/null
+++ b/src/Form/BookType.php
@@ -0,0 +1,32 @@
+add('Title')
+ ->add('language')
+ ->add('description')
+ ->add('publisher')
+ ->add('publish_date')
+ ->add('ebook', FileType::class, ['mapped' => false, 'data_class' => null, 'required' => false])
+ ->add('cover', FileType::class, ['mapped' => false, 'data_class' => null, 'required' => false])
+ ;
+ }
+
+ public function configureOptions(OptionsResolver $resolver): void
+ {
+ $resolver->setDefaults([
+ 'data_class' => Book::class,
+ ]);
+ }
+}
diff --git a/src/Repository/BookRepository.php b/src/Repository/BookRepository.php
new file mode 100644
index 0000000..079cddb
--- /dev/null
+++ b/src/Repository/BookRepository.php
@@ -0,0 +1,66 @@
+
+ *
+ * @method Book|null find($id, $lockMode = null, $lockVersion = null)
+ * @method Book|null findOneBy(array $criteria, array $orderBy = null)
+ * @method Book[] findAll()
+ * @method Book[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
+ */
+class BookRepository extends ServiceEntityRepository
+{
+ public function __construct(ManagerRegistry $registry)
+ {
+ parent::__construct($registry, Book::class);
+ }
+
+ public function add(Book $entity, bool $flush = false): void
+ {
+ $this->getEntityManager()->persist($entity);
+
+ if ($flush) {
+ $this->getEntityManager()->flush();
+ }
+ }
+
+ public function remove(Book $entity, bool $flush = false): void
+ {
+ $this->getEntityManager()->remove($entity);
+
+ if ($flush) {
+ $this->getEntityManager()->flush();
+ }
+ }
+
+// /**
+// * @return Book[] Returns an array of Book objects
+// */
+// public function findByExampleField($value): array
+// {
+// return $this->createQueryBuilder('b')
+// ->andWhere('b.exampleField = :val')
+// ->setParameter('val', $value)
+// ->orderBy('b.id', 'ASC')
+// ->setMaxResults(10)
+// ->getQuery()
+// ->getResult()
+// ;
+// }
+
+// public function findOneBySomeField($value): ?Book
+// {
+// return $this->createQueryBuilder('b')
+// ->andWhere('b.exampleField = :val')
+// ->setParameter('val', $value)
+// ->getQuery()
+// ->getOneOrNullResult()
+// ;
+// }
+}
diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php
new file mode 100644
index 0000000..a53d704
--- /dev/null
+++ b/src/Twig/AppExtension.php
@@ -0,0 +1,22 @@
+
-
-
- {% block title %}Welcome!{% endblock %}
-
- {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
- {% block stylesheets %}
- {{ encore_entry_link_tags('app') }}
- {% endblock %}
+
+
+ {% block title %}Welcome!{% endblock %}
+
+
- {% block javascripts %}
- {{ encore_entry_script_tags('app') }}
- {% endblock %}
-
-
- {% block body %}{% endblock %}
-
+ {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
+ {% block stylesheets %}
+ {# {{ encore_entry_link_tags('app') }} #}
+ {% endblock %}
+
+ {% block javascripts %}
+ {# {{ encore_entry_script_tags('app') }} #}
+ {% endblock %}
+
+
+
+ {% block body %}{% endblock %}
+
+
diff --git a/templates/book/_delete_form.html.twig b/templates/book/_delete_form.html.twig
new file mode 100644
index 0000000..9dcce07
--- /dev/null
+++ b/templates/book/_delete_form.html.twig
@@ -0,0 +1,4 @@
+
diff --git a/templates/book/_form.html.twig b/templates/book/_form.html.twig
new file mode 100644
index 0000000..9328bd5
--- /dev/null
+++ b/templates/book/_form.html.twig
@@ -0,0 +1,4 @@
+{{ form_start(form) }}
+ {{ form_widget(form) }}
+ {{ button_label|default('Save') }}
+{{ form_end(form) }}
diff --git a/templates/book/edit.html.twig b/templates/book/edit.html.twig
new file mode 100644
index 0000000..fdfe499
--- /dev/null
+++ b/templates/book/edit.html.twig
@@ -0,0 +1,13 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Edit Book{% endblock %}
+
+{% block body %}
+ Edit Book
+
+ {{ include('book/_form.html.twig', {'button_label': 'Update'}) }}
+
+ back to list
+
+ {{ include('book/_delete_form.html.twig') }}
+{% endblock %}
diff --git a/templates/book/index.html.twig b/templates/book/index.html.twig
new file mode 100644
index 0000000..95719bd
--- /dev/null
+++ b/templates/book/index.html.twig
@@ -0,0 +1,49 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Book index{% endblock %}
+
+{% block body %}
+ Book index
+
+
+
+
+ Cover
+ Id
+ Title
+ Language
+ Description
+ Publisher
+ Publish_date
+ Filename
+ Original_filename
+ actions
+
+
+
+ {% for book in books %}
+
+ {% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %} {% endif %}
+ {{ book.id }}
+ {{ book.Title }}
+ {{ book.language }}
+ {{ book.description }}
+ {{ book.publisher }}
+ {{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}
+ {{ book.filename }}
+ {{ book.originalFilename }}
+
+ show
+ edit
+
+
+ {% else %}
+
+ no records found
+
+ {% endfor %}
+
+
+
+ Create new
+{% endblock %}
diff --git a/templates/book/new.html.twig b/templates/book/new.html.twig
new file mode 100644
index 0000000..44bc059
--- /dev/null
+++ b/templates/book/new.html.twig
@@ -0,0 +1,11 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}New Book{% endblock %}
+
+{% block body %}
+ Create new Book
+
+ {{ include('book/_form.html.twig') }}
+
+ back to list
+{% endblock %}
diff --git a/templates/book/show.html.twig b/templates/book/show.html.twig
new file mode 100644
index 0000000..adf1150
--- /dev/null
+++ b/templates/book/show.html.twig
@@ -0,0 +1,50 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Book{% endblock %}
+
+{% block body %}
+ Book
+
+
+
+
+ Id
+ {{ book.id }}
+
+
+ Title
+ {{ book.Title }}
+
+
+ Language
+ {{ book.language }}
+
+
+ Description
+ {{ book.description }}
+
+
+ Publisher
+ {{ book.publisher }}
+
+
+ Publish_date
+ {{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}
+
+
+ Filename
+ {{ book.filename }}
+
+
+ Original_filename
+ {{ book.originalFilename }}
+
+
+
+
+ back to list
+
+ edit
+
+ {{ include('book/_delete_form.html.twig') }}
+{% endblock %}
diff --git a/webpack.config.js b/webpack.config.js
deleted file mode 100644
index 056b04a..0000000
--- a/webpack.config.js
+++ /dev/null
@@ -1,75 +0,0 @@
-const Encore = require('@symfony/webpack-encore');
-
-// Manually configure the runtime environment if not already configured yet by the "encore" command.
-// It's useful when you use tools that rely on webpack.config.js file.
-if (!Encore.isRuntimeEnvironmentConfigured()) {
- Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
-}
-
-Encore
- // directory where compiled assets will be stored
- .setOutputPath('public/build/')
- // public path used by the web server to access the output path
- .setPublicPath('/build')
- // only needed for CDN's or sub-directory deploy
- //.setManifestKeyPrefix('build/')
-
- /*
- * ENTRY CONFIG
- *
- * Each entry will result in one JavaScript file (e.g. app.js)
- * and one CSS file (e.g. app.css) if your JavaScript imports CSS.
- */
- .addEntry('app', './assets/app.js')
-
- // enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
- .enableStimulusBridge('./assets/controllers.json')
-
- // When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
- .splitEntryChunks()
-
- // will require an extra script tag for runtime.js
- // but, you probably want this, unless you're building a single-page app
- .enableSingleRuntimeChunk()
-
- /*
- * FEATURE CONFIG
- *
- * Enable & configure other features below. For a full
- * list of features, see:
- * https://symfony.com/doc/current/frontend.html#adding-more-features
- */
- .cleanupOutputBeforeBuild()
- .enableBuildNotifications()
- .enableSourceMaps(!Encore.isProduction())
- // enables hashed filenames (e.g. app.abc123.css)
- .enableVersioning(Encore.isProduction())
-
- .configureBabel((config) => {
- config.plugins.push('@babel/plugin-proposal-class-properties');
- })
-
- // enables @babel/preset-env polyfills
- .configureBabelPresetEnv((config) => {
- config.useBuiltIns = 'usage';
- config.corejs = 3;
- })
-
- // enables Sass/SCSS support
- //.enableSassLoader()
-
- // uncomment if you use TypeScript
- //.enableTypeScriptLoader()
-
- // uncomment if you use React
- //.enableReactPreset()
-
- // uncomment to get integrity="..." attributes on your script & link tags
- // requires WebpackEncoreBundle 1.4 or higher
- //.enableIntegrityHashes(Encore.isProduction())
-
- // uncomment if you're having problems with a jQuery plugin
- //.autoProvidejQuery()
-;
-
-module.exports = Encore.getWebpackConfig();