commit cc435e167808b64f20d3a514a08778d49fb2fad2
Author: Petr Lukašík <lukasik@rtsoft.cz>
Date:   Wed Apr 24 17:06:46 2019 +0200

    Re #7331 Implementace správy knih v administraci

diff --git a/app/AdminModule/component/Book/BookEditForm.latte b/app/AdminModule/component/Book/BookEditForm.latte
new file mode 100644
index 0000000..b6a732f
--- /dev/null
+++ b/app/AdminModule/component/Book/BookEditForm.latte
@@ -0,0 +1,5 @@
+<div class="row">
+    <div class="col-4">
+        {control form}
+    </div>
+</div>
\ No newline at end of file
diff --git a/app/AdminModule/component/Book/BookEditForm.php b/app/AdminModule/component/Book/BookEditForm.php
new file mode 100644
index 0000000..b416102
--- /dev/null
+++ b/app/AdminModule/component/Book/BookEditForm.php
@@ -0,0 +1,117 @@
+<?php
+
+
+namespace App\AdminModule\Components;
+
+
+use App\Enum\EFlashMessage;
+use App\Model\Repository\BookRepository;
+use App\Utils\Form;
+use Nette\Application\UI\Control;
+
+class BookEditForm extends Control
+{
+    private $bookId;
+
+    /**
+     * @var Form
+     */
+    private $form;
+    /**
+     * @var BookRepository
+     */
+    private $bookRepository;
+
+    public function __construct(BookRepository $bookRepository)
+    {
+        parent::__construct();
+
+        $this->form = new Form;
+        $this->bookId = NULL;
+        $this->bookRepository = $bookRepository;
+    }
+
+    public function render()
+    {
+        $this->template->setFile(__DIR__ . '/BookEditForm.latte');
+        $this->template->render();
+    }
+
+    public function createComponentForm()
+    {
+        $this->form->addText(BookRepository::COLUMN_BOOK_ABREV, 'Abbreviation')
+            ->addRule(Form::REQUIRED, 'Field %label is required', TRUE);
+        $this->form->addText(BookRepository::COLUMN_BOOK_AUTHOR, 'Author');
+        $this->form->addText(BookRepository::COLUMN_BOOK_NAME, 'Name')
+            ->addRule(Form::REQUIRED, 'Field %label is required', TRUE);
+        $this->form->addText(BookRepository::COLUMN_BOOK_SUBTITLE, 'Alternate name');
+        $this->form->addTextArea(BookRepository::COLUMN_BOOK_DESCRIPTION, 'Description');
+        $this->form->addText(BookRepository::COLUMN_PLACE_OF_PUB, 'Publication place');
+        $this->form->addText(BookRepository::COLUMN_DATE_OF_PUB, 'Publication date');
+        $this->form->addText(BookRepository::COLUMN_PAGES, 'Pages');
+        $this->form->addText(BookRepository::COLUMN_VOLUME, 'Volume');
+        $this->form->addText(BookRepository::COLUMN_VOLUME_NO, 'Volume No.');
+
+        $this->form->setDefaults($this->getDefaults());
+
+        $this->form->addSubmit('submit', 'Save');
+
+        $this->form->onSuccess[] = [$this, 'formSuccess'];
+
+        return $this->form;
+    }
+
+    public function formSuccess(Form $form)
+    {
+        $result = $this->bookRepository->save($form->getValues(TRUE), $this->bookId);
+
+        if ($result)
+        {
+            $this->presenter->flashMessage('Book was added successfully.', EFlashMessage::SUCCESS);
+            $this->presenter->redirect('Book:edit', ['id' => $result->{BookRepository::COLUMN_ID}]);
+        } else
+        {
+            $form->addError('Book couldn\'t be added. Please try it again later.');
+        }
+    }
+
+    /**
+     * Nastavení ID při editaci
+     *
+     * @param int $bookId
+     */
+    public function setId(int $bookId)
+    {
+        $this->bookId = $bookId;
+    }
+
+    /**
+     * Vrací hodnoty z databáze při editaci existující knihy
+     *
+     * @return array
+     */
+    public function getDefaults()
+    {
+        $defaultValues = array();
+
+        if (!empty($this->bookId))
+        {
+            $bookRow = $this->bookRepository->findRow($this->bookId);
+
+            if ($bookRow)
+            {
+                $defaultValues = $bookRow->toArray();
+            }
+        }
+
+        return $defaultValues;
+    }
+}
+
+interface IBookEditFormFactory
+{
+    /**
+     * @return BookEditForm
+     */
+    public function create();
+}
\ No newline at end of file
diff --git a/app/AdminModule/component/Book/BookGrid.php b/app/AdminModule/component/Book/BookGrid.php
new file mode 100644
index 0000000..19d2887
--- /dev/null
+++ b/app/AdminModule/component/Book/BookGrid.php
@@ -0,0 +1,86 @@
+<?php
+
+
+namespace App\AdminModule\Components;
+
+use App\Model\Repository\BookRepository;
+use App\Utils\DataGrid\DataGrid;
+use Ublaboo\DataGrid\Exception\DataGridException;
+
+class BookGrid extends DataGrid
+{
+    /**
+     * @var BookRepository
+     */
+    private $bookRepository;
+
+    public function __construct(BookRepository $bookRepository)
+    {
+        $this->bookRepository = $bookRepository;
+
+        parent::__construct(false);
+    }
+
+    /**
+     * Abstraktní metoda, slouží k nastavení primárního klíče a nastavení datasource
+     *  1. $this->setPrimaryKey();
+     *  2. $this->setDataSource();
+     *
+     * @throws DataGridException
+     */
+    public function init()
+    {
+        $this->setPrimaryKey(BookRepository::COLUMN_ID);
+        $this->setDataSource($this->bookRepository->findAll()->order(BookRepository::COLUMN_BOOK_ABREV));
+    }
+
+    /**
+     * Definice sloupečků, akcí, vyhledávácích filtrů gridu
+     *
+     * @throws DataGridException
+     */
+    public function define()
+    {
+        // Definice sloupečků
+        $this->addColumnNumber(BookRepository::COLUMN_ID, 'ID')->setDefaultHide(TRUE);
+        $this->addColumnText(BookRepository::COLUMN_BOOK_ABREV, 'Abbreviation')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_BOOK_AUTHOR, 'Author')->addAttributes(["width" => "10%"])->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_BOOK_NAME, 'Name')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_BOOK_SUBTITLE, 'Alternate name')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_BOOK_DESCRIPTION, 'Description')->addAttributes(["width" => "20%"])->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_PLACE_OF_PUB, 'Publication place')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_DATE_OF_PUB, 'Publication date')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_PAGES, 'Pages')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_VOLUME, 'Volume')->setAlign('center');
+        $this->addColumnText(BookRepository::COLUMN_VOLUME_NO, 'Volume No.')->setAlign('center');
+
+        // Definice filtrů
+        $this->addFilterText(BookRepository::COLUMN_BOOK_ABREV, 'Abbreviation');
+        $this->addFilterText(BookRepository::COLUMN_BOOK_AUTHOR, 'Author');
+        $this->addFilterText(BookRepository::COLUMN_BOOK_NAME, 'Name');
+        $this->addFilterText(BookRepository::COLUMN_BOOK_SUBTITLE, 'Alternate name');
+        $this->addFilterText(BookRepository::COLUMN_BOOK_DESCRIPTION, 'Description');
+        $this->addFilterText(BookRepository::COLUMN_PLACE_OF_PUB, 'Publication place');
+        $this->addFilterText(BookRepository::COLUMN_DATE_OF_PUB, 'Publication date');
+        $this->addFilterText(BookRepository::COLUMN_PAGES, 'Pages');
+        $this->addFilterText(BookRepository::COLUMN_VOLUME, 'Volume');
+        $this->addFilterText(BookRepository::COLUMN_VOLUME_NO, 'Volume No.');
+
+        // Definice akcí
+        $this->addAction('edit', 'edit', 'Book:edit', ['id' => BookRepository::COLUMN_ID])
+            ->setTitle('Edit');
+
+        $this->addAction('delete', 'delete', 'deleteBook!', ['id' => BookRepository::COLUMN_ID])
+            ->setConfirm('Do you really want to delete book %s.', BookRepository::COLUMN_BOOK_ABREV)
+            ->setTitle('Delete')
+            ->setClass('btn btn-xs btn-danger ajax');
+    }
+}
+
+interface IBookGridFactory
+{
+    /**
+     * @return BookGrid
+     */
+    public function create();
+}
\ No newline at end of file
diff --git a/app/AdminModule/presenters/BookPresenter.php b/app/AdminModule/presenters/BookPresenter.php
new file mode 100644
index 0000000..b2c228c
--- /dev/null
+++ b/app/AdminModule/presenters/BookPresenter.php
@@ -0,0 +1,85 @@
+<?php
+
+
+namespace App\AdminModule\Presenters;
+
+use App\AdminModule\Components\IBookEditFormFactory;
+use App\AdminModule\Components\IBookGridFactory;
+use App\Enum\EFlashMessage;
+use App\Model\Repository\BookRepository;
+
+class BookPresenter extends BaseUserPresenter
+{
+    /**
+     * @var IBookGridFactory
+     */
+    private $bookGridFactory;
+    /**
+     * @var IBookEditFormFactory
+     */
+    private $bookEditFormFactory;
+    /**
+     * @var BookRepository
+     */
+    private $bookRepository;
+
+    public function __construct(
+        IBookGridFactory $bookGridFactory,
+        IBookEditFormFactory $bookEditFormFactory,
+        BookRepository $bookRepository
+    )
+    {
+        parent::__construct();
+
+        $this->bookGridFactory = $bookGridFactory;
+        $this->bookEditFormFactory = $bookEditFormFactory;
+        $this->bookRepository = $bookRepository;
+    }
+
+    public function actionEdit(int $id)
+    {
+        $this->template->id = $id;
+        $this['bookEditForm']->setId($id);
+    }
+
+    /**
+     * Akce pro odstranění knihy
+     *
+     * @param int $id
+     * @throws \Nette\Application\AbortException
+     */
+    public function actionDelete(int $id)
+    {
+        $result = $this->bookRepository->findRow($id)->delete();
+        if ($result) {
+            $this->flashMessage('Book was successfully deleted.', EFlashMessage::SUCCESS);
+        } else {
+            $this->flashMessage('Book wasn\'t deleted.', EFlashMessage::ERROR);
+        }
+
+        $this->redirect('Book:default');
+    }
+
+    /**
+     * Handle používaný v BookGrid pro smazání knihy
+     *
+     * @param int $id : ID mazané knihy
+     */
+    public function handleDeleteBook(int $id)
+    {
+        if ($this->isAjax()) {
+            $this->bookRepository->findRow($id)->delete();
+            $this['bookGrid']->reload();
+        }
+    }
+
+    public function createComponentBookGrid()
+    {
+        return $this->bookGridFactory->create();
+    }
+
+    public function createComponentBookEditForm()
+    {
+        return $this->bookEditFormFactory->create();
+    }
+}
\ No newline at end of file
diff --git a/app/AdminModule/templates/@layout.latte b/app/AdminModule/templates/@layout.latte
index 5b1f1ce..dce76c2 100644
--- a/app/AdminModule/templates/@layout.latte
+++ b/app/AdminModule/templates/@layout.latte
@@ -99,7 +99,7 @@
     <li class="nav-item"><a n:href="User:default" n:class="nav-link, $presenter->isLinkCurrent('User:*') ? active" title="Users">
             Users </a></li>
 
-    <li class="nav-item"><a href="#" class="nav-link" title="Book">
+    <li class="nav-item"><a n:href="Book:default" n:class="nav-link, $presenter->isLinkCurrent('Book:*') ? active" title="Book">
             Book </a></li>
     <li class="nav-item"><a href="#" class="nav-link" title="Transliteration">
             Transliteration </a></li>
diff --git a/app/AdminModule/templates/Book/add.latte b/app/AdminModule/templates/Book/add.latte
new file mode 100644
index 0000000..56d53f4
--- /dev/null
+++ b/app/AdminModule/templates/Book/add.latte
@@ -0,0 +1,10 @@
+{block content}
+<div class="row">
+    <div class="col-11">
+        <div class="display-5">New book</div>
+    </div>
+    <div class="col-1">
+        <a n:href="Book:default" class="btn btn-sm btn-success"><span class="fa fa-fw fa-list"></span> Book list</a>
+    </div>
+</div>
+{control bookEditForm}
\ No newline at end of file
diff --git a/app/AdminModule/templates/Book/default.latte b/app/AdminModule/templates/Book/default.latte
new file mode 100644
index 0000000..e957c8d
--- /dev/null
+++ b/app/AdminModule/templates/Book/default.latte
@@ -0,0 +1,14 @@
+{block content}
+<div class="row">
+    <div class="col-11">
+        <div class="display-5">Book List</div>
+    </div>
+    <div class="col-1">
+        <a n:href="Book:add" class="btn btn-sm btn-success"><span class="fa fa-fw fa-plus"></span> New Book</a>
+    </div>
+</div>
+<div class="row">
+    <div class="col-10 offset-1">
+        {control bookGrid}
+    </div>
+</div>
\ No newline at end of file
diff --git a/app/AdminModule/templates/Book/edit.latte b/app/AdminModule/templates/Book/edit.latte
new file mode 100644
index 0000000..77a2387
--- /dev/null
+++ b/app/AdminModule/templates/Book/edit.latte
@@ -0,0 +1,11 @@
+{block content}
+<div class="row">
+    <div class="col-10">
+        <div class="display-5">Edit Book</div>
+    </div>
+    <div class="col-2 text-right">
+        <a n:href="Book:default" class="btn btn-sm btn-success"><span class="fa fa-fw fa-list"></span> Book list</a>
+        <a n:href="Book:delete $id" class="btn btn-sm btn-danger" onclick="return confirm('Do you really want to delete this book?')"><span class="fa fa-fw fa-trash"></span> Delete book</a>
+    </div>
+</div>
+{control bookEditForm}
\ No newline at end of file
diff --git a/app/config/components.neon b/app/config/components.neon
index 1033e2b..29e36e6 100644
--- a/app/config/components.neon
+++ b/app/config/components.neon
@@ -7,6 +7,7 @@ services:
     - App\AdminModule\Components\IOriginGridFactory
     - App\AdminModule\Components\ISurfaceTypeGridFactory
     - App\AdminModule\Components\IBookTypeGridFactory
+    - App\AdminModule\Components\IBookGridFactory
 
     # Formuláře
     - App\FrontModule\Components\ILoginFormFactory
@@ -16,4 +17,5 @@ services:
     - App\AdminModule\Components\IOriginEditFormFactory
     - App\AdminModule\Components\ISurfaceTypeEditFormFactory
     - App\AdminModule\Components\IMuseumEditFormFactory
-    - App\AdminModule\Components\IBookTypeEditFormFactory
\ No newline at end of file
+    - App\AdminModule\Components\IBookTypeEditFormFactory
+    - App\AdminModule\Components\IBookEditFormFactory
\ No newline at end of file
