Styled book form and added an ux dropzone component.
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
<div v-if="selectedBook && selectedBook.cover_url.small">
|
<div v-if="selectedBook && selectedBook.cover_url.small">
|
||||||
<img :src="selectedBook.cover_url.small" class="img-thumbnail"/>
|
<img :src="selectedBook.cover_url.small" class="img-thumbnail"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="book in books">
|
<div v-if="books.length" v-for="book in books">
|
||||||
<div class="d-flex flex-row border mb-3 cursor-pointer book-search-item" @click="getBookDetails(book.url)">
|
<div class="d-flex flex-row border mb-3 cursor-pointer book-search-item" @click="getBookDetails(book.url)">
|
||||||
<img :src="book.cover_url.small" class="img-fluid rounded-start">
|
<img :src="book.cover_url.small" class="img-fluid rounded-start">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -21,8 +21,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<slot></slot>
|
<h1 v-else>Oh no 😢</h1>
|
||||||
<BookForm></BookForm>
|
|
||||||
|
<div v-show="manualMode" >
|
||||||
|
<slot></slot>
|
||||||
|
<BookForm></BookForm>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -37,7 +41,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
searchTerm: null,
|
searchTerm: null,
|
||||||
books: [],
|
books: [],
|
||||||
selectedBook: null
|
selectedBook: null,
|
||||||
|
manualMode: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -48,7 +53,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
getBookDetails: function (url) {
|
getBookDetails: function (url) {
|
||||||
console.info(url);
|
this.manualMode = true;
|
||||||
axios.get('/book/info/' + btoa(url)).then(response => {
|
axios.get('/book/info/' + btoa(url)).then(response => {
|
||||||
const book = this.selectedBook = response.data;
|
const book = this.selectedBook = response.data;
|
||||||
this.$el.querySelector('#book_title').value = book.title;
|
this.$el.querySelector('#book_title').value = book.title;
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ return [
|
|||||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||||
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
||||||
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
||||||
|
Symfony\UX\Dropzone\DropzoneBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ use App\Entity\File;
|
|||||||
use App\Form\BookType;
|
use App\Form\BookType;
|
||||||
use App\Repository\BookRepository;
|
use App\Repository\BookRepository;
|
||||||
use App\Repository\FileRepository;
|
use App\Repository\FileRepository;
|
||||||
|
use App\Service\FileService;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Techtube\Bookinfo\BookFinder;
|
use Techtube\Bookinfo\BookFinder;
|
||||||
use Techtube\Bookinfo\DataParser;
|
|
||||||
|
|
||||||
#[Route('/book')]
|
#[Route('/book')]
|
||||||
class BookController extends AbstractController
|
class BookController extends AbstractController
|
||||||
@@ -143,10 +142,12 @@ class BookController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}', name: 'app_book_delete', methods: ['POST'])]
|
#[Route('/{id}', name: 'app_book_delete', methods: ['POST'])]
|
||||||
public function delete(Request $request, Book $book, BookRepository $bookRepository): Response
|
public function delete(Request $request, Book $book, BookRepository $bookRepository, FileService $fileService): Response
|
||||||
{
|
{
|
||||||
if ($this->isCsrfTokenValid('delete' . $book->getId(), $request->request->get('_token'))) {
|
if ($this->isCsrfTokenValid('delete' . $book->getId(), $request->request->get('_token'))) {
|
||||||
|
$fileService->removeFiles($book->getFiles());
|
||||||
$bookRepository->remove($book, true);
|
$bookRepository->remove($book, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
|
return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
|||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\UX\Dropzone\Form\DropzoneType;
|
||||||
|
|
||||||
class BookType extends AbstractType
|
class BookType extends AbstractType
|
||||||
{
|
{
|
||||||
@@ -52,9 +53,9 @@ class BookType extends AbstractType
|
|||||||
'required' => false,
|
'required' => false,
|
||||||
'attr' => ['accept' => ".pdf, .epub, .mobi"]
|
'attr' => ['accept' => ".pdf, .epub, .mobi"]
|
||||||
])
|
])
|
||||||
->add('cover', FileType::class, ['mapped' => false, 'data_class' => null, 'required' => false])
|
// ->add('cover', FileType::class, ['mapped' => false, 'data_class' => null, 'required' => false])
|
||||||
->add('cover_url', TextType::class, ['mapped' => false, 'help' => 'Fill in the field with a link to a cover image to use it as a cover for the book.', 'label'=> 'Cover url', 'required' => false])
|
->add('cover_url', TextType::class, ['mapped' => false, 'help' => 'Fill in the field with a link to a cover image to use it as a cover for the book.', 'label'=> 'Cover url', 'required' => false])
|
||||||
|
->add('cover', DropzoneType::class, ['mapped' => false, 'data_class' => null, 'required' => false, 'attr' => ['data-controller' => 'mydropzone', 'accept' => "image/*", 'placeholder' => 'Drag and drop or browse']])
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
<form method="post" action="{{ path('app_book_delete', {'id': book.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
<div class="card border-danger mb-3 mt-5" style="">
|
||||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ book.id) }}">
|
<div class="card-header text-danger">Danger zone</div>
|
||||||
<button class="btn btn-danger">Delete</button>
|
<div class="card-body text-danger">
|
||||||
</form>
|
<h5 class="card-title">Delete book with all the information and files</h5>
|
||||||
|
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
|
||||||
|
<form method="post" action="{{ path('app_book_delete', {'id': book.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ book.id) }}">
|
||||||
|
<button class="btn btn-danger">Delete</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,78 @@
|
|||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
{{ form_widget(form) }}
|
<div class="my-custom-class-for-errors">
|
||||||
<button class="btn btn-primary">{{ button_label|default('Save') }}</button>
|
{{ form_errors(form) }}
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
{# <input type="text" name="sss" v-model="xxx" /> #}
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ form_row(form.title) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ form_row(form.subtitle) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ form_row(form.author) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ form_row(form.category) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.isbn) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
{{ form_row(form.pages) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ form_row(form.tags) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.publish_date) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.publisher) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.language) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.series) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.volume) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form_row(form.rating) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
{{ form_row(form.description) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
{{ form_row(form.ebook) }}
|
||||||
|
</div>
|
||||||
|
{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}
|
||||||
|
<div class="col-md-1 mt-4">
|
||||||
|
<img class="img-thumbnail"
|
||||||
|
style="max-width: 80px"
|
||||||
|
src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}"/>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}col-md-4 {% else %} col-md-6 {% endif %}">
|
||||||
|
{{ form_row(form.cover) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{ form_row(form.cover_url) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-primary">{{ button_label|default('Save') }}</button>
|
||||||
|
<a href="{{ path('app_book_index') }}" class="btn btn-light">Back to list</a>
|
||||||
|
|
||||||
{{ form_end(form) }}
|
{{ form_end(form) }}
|
||||||
|
|||||||
Reference in New Issue
Block a user