Added:
- toolbar and fixes
This commit is contained in:
6
Makefile
6
Makefile
@@ -150,3 +150,9 @@ npm-run: ## Run the dev server
|
||||
|
||||
npm-watch: ## Watch for changes
|
||||
@$(DOCKER_COMP) exec node npm run watch
|
||||
|
||||
npm-add: ## Add a package as a dependency make npm-add p=package-name
|
||||
@$(DOCKER_COMP) exec node npm install $(p)
|
||||
|
||||
npm-add-dev: ## Add a package as a dev dependency make npm-add-dev p=package-name
|
||||
@$(DOCKER_COMP) exec node npm install $(p) --save-dev
|
||||
|
||||
45
assets/controllers/dropdown_controller.js
Normal file
45
assets/controllers/dropdown_controller.js
Normal file
@@ -0,0 +1,45 @@
|
||||
// assets/controllers/dropdown_controller.js
|
||||
import {Controller} from "@hotwired/stimulus"
|
||||
import {useClickOutside} from "stimulus-use"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["button", "menu"]
|
||||
|
||||
connect() {
|
||||
useClickOutside(this)
|
||||
}
|
||||
|
||||
toggle(event) {
|
||||
this.menuTarget.classList.toggle('hidden')
|
||||
if (!this.menuTarget.classList.contains('hidden')) {
|
||||
this.positionMenu()
|
||||
}
|
||||
}
|
||||
|
||||
clickOutside(event) {
|
||||
this.menuTarget.classList.add('hidden')
|
||||
}
|
||||
|
||||
positionMenu() {
|
||||
const buttonRect = this.buttonTarget.getBoundingClientRect()
|
||||
const menuRect = this.menuTarget.getBoundingClientRect()
|
||||
const spaceRight = window.innerWidth - buttonRect.right
|
||||
const spaceBottom = window.innerHeight - buttonRect.bottom
|
||||
|
||||
if (spaceRight < menuRect.width && buttonRect.left > menuRect.width) {
|
||||
this.menuTarget.style.left = 'auto'
|
||||
this.menuTarget.style.right = '0'
|
||||
} else {
|
||||
this.menuTarget.style.left = '0'
|
||||
this.menuTarget.style.right = 'auto'
|
||||
}
|
||||
|
||||
if (spaceBottom < menuRect.height && buttonRect.top > menuRect.height) {
|
||||
this.menuTarget.style.top = 'auto'
|
||||
this.menuTarget.style.bottom = '100%'
|
||||
} else {
|
||||
this.menuTarget.style.top = '100%'
|
||||
this.menuTarget.style.bottom = 'auto'
|
||||
}
|
||||
}
|
||||
}
|
||||
59
assets/controllers/toolbar_controller.js
Normal file
59
assets/controllers/toolbar_controller.js
Normal file
@@ -0,0 +1,59 @@
|
||||
// assets/controllers/toolbar_controller.js
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["dropdown"]
|
||||
static values = {
|
||||
currentSort: String,
|
||||
currentOrder: String
|
||||
}
|
||||
|
||||
refresh() {
|
||||
console.log("Refreshing...")
|
||||
}
|
||||
|
||||
syncRss() {
|
||||
console.log("Syncing RSS...")
|
||||
}
|
||||
|
||||
search() {
|
||||
console.log("Searching...")
|
||||
}
|
||||
|
||||
import() {
|
||||
console.log("Importing...")
|
||||
}
|
||||
|
||||
editMangas() {
|
||||
console.log("Editing mangas...")
|
||||
}
|
||||
|
||||
showOptions() {
|
||||
console.log("Showing options...")
|
||||
}
|
||||
|
||||
changeView() {
|
||||
console.log("Changing view...")
|
||||
}
|
||||
|
||||
sort(event) {
|
||||
event.preventDefault()
|
||||
const sortOption = event.currentTarget.dataset.sortOption
|
||||
let order = 'asc'
|
||||
|
||||
if (sortOption === this.currentSortValue && this.currentOrderValue === 'asc') {
|
||||
order = 'desc'
|
||||
}
|
||||
|
||||
const url = new URL(window.location)
|
||||
url.searchParams.set('sort', sortOption)
|
||||
url.searchParams.set('order', order)
|
||||
|
||||
window.location = url.toString()
|
||||
}
|
||||
|
||||
filter() {
|
||||
console.log("Filtering...")
|
||||
}
|
||||
|
||||
}
|
||||
21
package-lock.json
generated
21
package-lock.json
generated
@@ -26,6 +26,7 @@
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"sass": "^1.59.3",
|
||||
"sass-loader": "^13.2.0",
|
||||
"stimulus-use": "^0.52.2",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-notifier": "^1.15.0"
|
||||
@@ -5706,6 +5707,16 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/hotkeys-js": {
|
||||
"version": "3.13.7",
|
||||
"resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.13.7.tgz",
|
||||
"integrity": "sha512-ygFIdTqqwG4fFP7kkiYlvayZppeIQX2aPpirsngkv1xM1lP0piDY5QEh68nQnIKvz64hfocxhBaD/uK3sSK1yQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/hpack.js": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
|
||||
@@ -9207,6 +9218,16 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/stimulus-use": {
|
||||
"version": "0.52.2",
|
||||
"resolved": "https://registry.npmjs.org/stimulus-use/-/stimulus-use-0.52.2.tgz",
|
||||
"integrity": "sha512-413+tIw9n6Jnb0OFiQE1i3aP01i0hhGgAnPp1P6cNuBbhhqG2IOp8t1O/4s5Tw2lTvSYrFeLNdaY8sYlDaULeg==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@hotwired/stimulus": ">= 3",
|
||||
"hotkeys-js": ">= 3"
|
||||
}
|
||||
},
|
||||
"node_modules/streamx": {
|
||||
"version": "2.18.0",
|
||||
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"sass": "^1.59.3",
|
||||
"sass-loader": "^13.2.0",
|
||||
"stimulus-use": "^0.52.2",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-notifier": "^1.15.0"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Manager\ToolbarManager;
|
||||
use App\Message\DownloadChapter;
|
||||
use App\Repository\ChapterRepository;
|
||||
use Doctrine\DBAL\Connection;
|
||||
@@ -13,7 +14,11 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class ActivityController extends AbstractController
|
||||
{
|
||||
public function __construct(private Connection $connection, private readonly ChapterRepository $chapterRepository)
|
||||
public function __construct(
|
||||
private readonly Connection $connection,
|
||||
private readonly ChapterRepository $chapterRepository,
|
||||
private readonly ToolbarManager $toolbarManager
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -33,6 +38,7 @@ class ActivityController extends AbstractController
|
||||
return $this->render('activity/index.html.twig', [
|
||||
'controller_name' => 'ActivityController',
|
||||
'status' => $status,
|
||||
'toolbarItems' => $this->toolbarManager->getToolbarItems(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Controller;
|
||||
|
||||
use App\Entity\Chapter;
|
||||
use App\Entity\Manga;
|
||||
use App\Manager\ToolbarManager;
|
||||
use App\Message\DownloadChapter;
|
||||
use App\Repository\ChapterRepository;
|
||||
use App\Repository\MangaRepository;
|
||||
@@ -34,19 +35,23 @@ class MangaController extends AbstractController
|
||||
private readonly ChapterRepository $chapterRepository,
|
||||
private readonly MangaUpdatesMetadataProvider $mangaUpdatesDbProvider,
|
||||
private readonly MessageBusInterface $bus,
|
||||
private readonly CbzService $cbzService
|
||||
private readonly CbzService $cbzService,
|
||||
private readonly ToolbarManager $toolbarManager
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
#[Route('/manga', name: 'app_manga')]
|
||||
public function index(): Response
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
// phpinfo();
|
||||
$mangas = $this->mangaRepository->findAll();
|
||||
$sort = $request->query->get('sort', 'title');
|
||||
$order = $request->query->get('order', 'asc');
|
||||
|
||||
$mangas = $this->mangaRepository->findAllSorted($sort, $order);
|
||||
|
||||
return $this->render('manga/index.html.twig', [
|
||||
'controller_name' => 'MangaController',
|
||||
'mangas' => $mangas,
|
||||
'toolbarItems' => $this->toolbarManager->getToolbarItems(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -89,6 +94,7 @@ class MangaController extends AbstractController
|
||||
return $this->render('manga/show_chapters.html.twig', [
|
||||
'chapters_by_volume' => $chaptersByVolume,
|
||||
'manga' => $manga,
|
||||
'toolbarItems' => $this->toolbarManager->getToolbarItems(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
41
src/Manager/ToolbarManager.php
Normal file
41
src/Manager/ToolbarManager.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Manager;
|
||||
|
||||
class ToolbarManager
|
||||
{
|
||||
public function getToolbarItems(): array
|
||||
{
|
||||
return [
|
||||
'sortItems' => $this->getSortItems(),
|
||||
'filterItems' => $this->getFilterItems(),
|
||||
'viewOptions' => $this->getViewOptions()
|
||||
];
|
||||
}
|
||||
|
||||
private function getSortItems(): array
|
||||
{
|
||||
return [
|
||||
['text' => 'Par titre', 'action' => 'sort', 'data' => ['sort-option' => 'title']],
|
||||
['text' => 'Par année de publication', 'action' => 'sort', 'data' => ['sort-option' => 'publicationYear']],
|
||||
['text' => 'Par date d\'ajout', 'action' => 'sort', 'data' => ['sort-option' => 'createdAt']]
|
||||
];
|
||||
}
|
||||
|
||||
private function getFilterItems(): array
|
||||
{
|
||||
return [
|
||||
['text' => 'Tous les genres', 'action' => 'filter', 'data' => ['filter-option' => 'allGenres']],
|
||||
['text' => 'Mangas terminés', 'action' => 'filter', 'data' => ['filter-option' => 'completed']],
|
||||
['text' => 'Mangas en cours', 'action' => 'filter', 'data' => ['filter-option' => 'ongoing']]
|
||||
];
|
||||
}
|
||||
|
||||
private function getViewOptions(): array
|
||||
{
|
||||
return [
|
||||
['text' => 'Vue grille', 'action' => 'changeView', 'data' => ['view-option' => 'grid']],
|
||||
['text' => 'Vue liste', 'action' => 'changeView', 'data' => ['view-option' => 'list']]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -87,11 +87,6 @@ class MangaRepository extends ServiceEntityRepository
|
||||
return $sortedEntities;
|
||||
}
|
||||
|
||||
private function normalizeSlug(string $slug): string
|
||||
{
|
||||
return strtolower(preg_replace('/[^a-z0-9]+/i', '', $slug));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NonUniqueResultException
|
||||
*/
|
||||
@@ -108,6 +103,28 @@ class MangaRepository extends ServiceEntityRepository
|
||||
return $query->getQuery()->getOneOrNullResult();
|
||||
}
|
||||
|
||||
public function findAllSorted(string $sort = 'title', string $order = 'asc'): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('m');
|
||||
|
||||
switch ($sort) {
|
||||
case 'title':
|
||||
$qb->orderBy('m.title', $order);
|
||||
break;
|
||||
case 'publicationYear':
|
||||
$qb->orderBy('m.publicationYear', $order);
|
||||
break;
|
||||
case 'createdAt':
|
||||
$qb->orderBy('m.createdAt', $order);
|
||||
break;
|
||||
// Ajoutez d'autres cas pour les différentes options de tri
|
||||
default:
|
||||
$qb->orderBy('m.title', 'asc');
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Manga[] Returns an array of Manga objects
|
||||
// */
|
||||
|
||||
16
src/Twig/Components/DropdownMenu.php
Normal file
16
src/Twig/Components/DropdownMenu.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Twig\Components;
|
||||
|
||||
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
|
||||
use Symfony\UX\LiveComponent\Attribute\LiveProp;
|
||||
use Symfony\UX\LiveComponent\DefaultActionTrait;
|
||||
|
||||
#[AsLiveComponent]
|
||||
class DropdownMenu
|
||||
{
|
||||
use DefaultActionTrait;
|
||||
|
||||
#[LiveProp (writable: true)]
|
||||
public ?array $items = null;
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
|
||||
use Symfony\UX\LiveComponent\Attribute\LiveAction;
|
||||
use Symfony\UX\LiveComponent\Attribute\LiveProp;
|
||||
@@ -27,6 +28,11 @@ class NewMangaForm
|
||||
#[LiveProp(writable: true)]
|
||||
public ?int $index = 0;
|
||||
|
||||
public function __construct(private UrlGeneratorInterface $urlGenerator)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function mount(Manga $manga): void
|
||||
{
|
||||
$this->manga = $manga;
|
||||
@@ -84,6 +90,8 @@ class NewMangaForm
|
||||
$manga->addChapter($chapter);
|
||||
}
|
||||
|
||||
$mangaChapterUrl = $this->urlGenerator->generate('app_manga_show', ['mangaSlug' => $manga->getSlug()]);
|
||||
|
||||
try {
|
||||
foreach ($manga->getChapters() as $chapter) {
|
||||
$entityManager->persist($chapter);
|
||||
@@ -93,11 +101,11 @@ class NewMangaForm
|
||||
$entityManager->flush();
|
||||
} catch (\Exception $e) {
|
||||
if ($e instanceof UniqueConstraintViolationException) {
|
||||
return new RedirectResponse('/manga/' . $manga->getSlug());
|
||||
return new RedirectResponse($mangaChapterUrl);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return new RedirectResponse('/manga/' . $manga->getSlug());
|
||||
return new RedirectResponse($mangaChapterUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,41 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block toolbar %}
|
||||
<div class="bg-gray-800 p-3 min-h-14">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<div class="flex mr-2 items-center">
|
||||
<twig:ToolBarButton icon="sync-alt" text="Tout actualiser"/>
|
||||
<twig:ToolBarButton icon="search" text="Rechercher le manga"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="sitemap" text="Aperçu renommage"/>
|
||||
<twig:ToolBarButton icon="user-plus" text="Importation manuelle"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="wrench" text="Éditer"/>
|
||||
<twig:ToolBarButton icon="trash-can" text="Supprimer"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% set left_group %}
|
||||
<twig:ToolBarButton icon="sync-alt" text="Tout actualiser" action="refresh"/>
|
||||
<twig:ToolBarButton icon="rss" text="Synchro RSS" action="syncRss"/>
|
||||
<twig:Divider/>
|
||||
<twig:ToolBarButton icon="search" text="Rechercher tout" action="search"/>
|
||||
<twig:ToolBarButton icon="user-plus" text="Importation manuelle" action="import"/>
|
||||
<twig:Divider/>
|
||||
<twig:ToolBarButton icon="wrench" text="Modifier Mangas" action="editMangas"/>
|
||||
|
||||
{% endset %}
|
||||
|
||||
{% set right_group %}
|
||||
<twig:ToolBarButton icon="th-large" text="Options" action="showOptions"/>
|
||||
<twig:DropdownMenu
|
||||
icon="eye"
|
||||
text="Vue"
|
||||
items="{{ toolbarItems.viewOptions }}"
|
||||
/>
|
||||
<twig:Divider/>
|
||||
<twig:DropdownMenu
|
||||
icon="sort"
|
||||
text="Trier"
|
||||
items="{{ toolbarItems.sortItems }}"
|
||||
/>
|
||||
<twig:DropdownMenu
|
||||
icon="filter"
|
||||
text="Filtre"
|
||||
items="{{ toolbarItems.filterItems }}"
|
||||
/>
|
||||
{% endset %}
|
||||
|
||||
<twig:Toolbar
|
||||
left_group="{{ left_group }}"
|
||||
right_group="{{ right_group }}"
|
||||
data-action="click@window->toolbar#clickOutside"
|
||||
/>
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="container mx-auto mt-2">
|
||||
|
||||
2
templates/components/Divider.html.twig
Normal file
2
templates/components/Divider.html.twig
Normal file
@@ -0,0 +1,2 @@
|
||||
{# templates/components/Divider.html.twig #}
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
29
templates/components/DropdownMenu.html.twig
Normal file
29
templates/components/DropdownMenu.html.twig
Normal file
@@ -0,0 +1,29 @@
|
||||
{# templates/components/DropdownMenu.html.twig #}
|
||||
<div {{ attributes }} >
|
||||
<div data-controller="dropdown" class="relative inline-block">
|
||||
<twig:ToolBarButton
|
||||
icon="{{ icon }}"
|
||||
text="{{ text }}"
|
||||
action="toggle"
|
||||
data-dropdown-target="button"
|
||||
/>
|
||||
<div class="absolute left-0 mt-2 w-max z-10 bg-gray-800 rounded-sm shadow-lg hidden"
|
||||
data-dropdown-target="menu" data-controller="toolbar">
|
||||
<div class="py-1">
|
||||
{% for item in items %}
|
||||
<a href="#"
|
||||
class="block px-4 py-2 text-sm text-white hover:text-green-500"
|
||||
data-action="toolbar#{{ item.action }}"
|
||||
{% if item.data is defined %}
|
||||
{% for key, value in item.data %}
|
||||
data-{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
>
|
||||
{{ item.text }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -35,7 +35,7 @@
|
||||
<span>{{ manga.title }}</span>
|
||||
<span class="text-2xl text-gray-500 ml-2">({{ manga.publicationYear }})</span>
|
||||
</div>
|
||||
<a href="{{ path('manga_show', { 'mangaSlug': manga.slug }) }}"
|
||||
<a href="{{ path('app_manga_show', { 'mangaSlug': manga.slug }) }}"
|
||||
class="text-gray-400 hover:text-gray-500">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<li class="px-4 py-2 text-gray-400">Mangas existants</li>
|
||||
{% for manga in this.mangas %}
|
||||
<li class="px-4 py-2 hover:bg-gray-600 cursor-pointer">
|
||||
<a class="flex items-center" href="{{ path('manga_show', { 'mangaSlug': manga.slug }) }}">
|
||||
<a class="flex items-center" href="{{ path('app_manga_show', { 'mangaSlug': manga.slug }) }}">
|
||||
<img src="{{ manga.imageUrl ?? 'https://placehold.co/40x60' }}" alt="{{ manga.title }}"
|
||||
class="w-10 h-15 object-cover mr-4">
|
||||
<span>{{ manga.title }} ({{ manga.publicationYear }})</span>
|
||||
@@ -26,7 +26,7 @@
|
||||
{% else %}
|
||||
<li class="px-4 py-2 text-gray-400">Aucun manga trouvé.</li>
|
||||
<li class="px-4 py-2 hover:bg-gray-600 cursor-pointer">
|
||||
<a class="flex items-center" href="{{ path('add_new_manga', {query: query}) }}">
|
||||
<a class="flex items-center" href="{{ path('app_manga_new', {query: query}) }}">
|
||||
<span>Ajouter {{ query }}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<div{{ attributes }}>
|
||||
<button class="flex flex-col justify-around min-h-14 w-min ml-4 items-center text-white group">
|
||||
{# templates/components/ToolbarButton.html.twig #}
|
||||
<div {{ attributes }}>
|
||||
<button
|
||||
class="flex flex-col justify-around min-h-14 w-min ml-4 items-center text-white group"
|
||||
{% if action %}
|
||||
{{ stimulus_action('dropdown', action) }}
|
||||
{% endif %}
|
||||
>
|
||||
<i class="fas fa-{{ icon }} text-xl group-hover:text-green-500"></i>
|
||||
<span class="text-xs">{{ text }}</span>
|
||||
</button>
|
||||
|
||||
11
templates/components/Toolbar.html.twig
Normal file
11
templates/components/Toolbar.html.twig
Normal file
@@ -0,0 +1,11 @@
|
||||
{# templates/components/Toolbar.html.twig #}
|
||||
<div class="bg-gray-800 p-3 min-h-14" {{ stimulus_controller('toolbar') }}>
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<div class="flex mr-2 items-center">
|
||||
{{ left_group|raw }}
|
||||
</div>
|
||||
<div class="flex mr-2 items-center">
|
||||
{{ right_group|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,31 +1,49 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block toolbar %}
|
||||
<div class="bg-gray-800 p-3 min-h-14">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<div class="flex mr-2 items-center">
|
||||
<twig:ToolBarButton icon="sync-alt" text="Tout actualiser"/>
|
||||
<twig:ToolBarButton icon="rss" text="Synchro RSS"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="search" text="Rechercher tout"/>
|
||||
<twig:ToolBarButton icon="user-plus" text="Importation manuelle"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="wrench" text="Modifier Mangas"/>
|
||||
</div>
|
||||
<div class="flex mr-2 items-center">
|
||||
<twig:ToolBarButton icon="th-large" text="Options"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="eye" text="Vue"/>
|
||||
<twig:ToolBarButton icon="sort" text="Trier"/>
|
||||
<twig:ToolBarButton icon="filter" text="Filtre"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% set left_group %}
|
||||
<twig:ToolBarButton icon="sync-alt" text="Tout actualiser" action="refresh"/>
|
||||
<twig:ToolBarButton icon="rss" text="Synchro RSS" action="syncRss"/>
|
||||
<twig:Divider/>
|
||||
<twig:ToolBarButton icon="search" text="Rechercher tout" action="search"/>
|
||||
<twig:ToolBarButton icon="user-plus" text="Importation manuelle" action="import"/>
|
||||
<twig:Divider/>
|
||||
<twig:ToolBarButton icon="wrench" text="Modifier Mangas" action="editMangas"/>
|
||||
|
||||
{% endset %}
|
||||
|
||||
{% set right_group %}
|
||||
<twig:ToolBarButton icon="th-large" text="Options" action="showOptions"/>
|
||||
<twig:DropdownMenu
|
||||
icon="eye"
|
||||
text="Vue"
|
||||
items="{{ toolbarItems.viewOptions }}"
|
||||
/>
|
||||
<twig:Divider/>
|
||||
<twig:DropdownMenu
|
||||
icon="sort"
|
||||
text="Trier"
|
||||
items="{{ toolbarItems.sortItems }}"
|
||||
/>
|
||||
<twig:DropdownMenu
|
||||
icon="filter"
|
||||
text="Filtre"
|
||||
items="{{ toolbarItems.filterItems }}"
|
||||
/>
|
||||
{% endset %}
|
||||
|
||||
<twig:Toolbar
|
||||
left_group="{{ left_group }}"
|
||||
right_group="{{ right_group }}"
|
||||
data-action="click@window->toolbar#clickOutside"
|
||||
/>
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="w-full p-4 grid sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-8 2xl:grid-cols-12 gap-4">
|
||||
{% for manga in mangas %}
|
||||
<div class="bg-white overflow-hidden border border-gray-200 hover:shadow-2xl hover:border-gray-400 transition-all duration-300 flex flex-col">
|
||||
<a href="{{ path('app_manga_show', { 'mangaSlug': manga.slug }) }}" class="block relative w-full pb-[150%] overflow-hidden">
|
||||
<div
|
||||
class="bg-white overflow-hidden border border-gray-200 hover:shadow-2xl hover:border-gray-400 transition-all duration-300 flex flex-col">
|
||||
<a href="{{ path('app_manga_show', { 'mangaSlug': manga.slug }) }}"
|
||||
class="block relative w-full pb-[150%] overflow-hidden">
|
||||
<img src="{{ manga.imageUrl ?? 'https://placehold.co/150x220' }}" alt="{{ manga.title }}"
|
||||
class="absolute top-0 left-0 w-full h-full object-cover">
|
||||
</a>
|
||||
|
||||
@@ -1,19 +1,41 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block toolbar %}
|
||||
<div class="bg-gray-800 p-3 min-h-14">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<div class="flex mr-2 items-center">
|
||||
<twig:ToolBarButton icon="sync-alt" text="Tout actualiser"/>
|
||||
<twig:ToolBarButton icon="search" text="Rechercher le manga"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="sitemap" text="Aperçu renommage"/>
|
||||
<twig:ToolBarButton icon="user-plus" text="Importation manuelle"/>
|
||||
<div class="min-h-14 mx-4 border-r opacity-50 border-green-500"></div>
|
||||
<twig:ToolBarButton icon="wrench" text="Éditer"/>
|
||||
<twig:ToolBarButton icon="trash-can" text="Supprimer"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% set left_group %}
|
||||
<twig:ToolBarButton icon="sync-alt" text="Tout actualiser" action="refresh"/>
|
||||
<twig:ToolBarButton icon="rss" text="Synchro RSS" action="syncRss"/>
|
||||
<twig:Divider/>
|
||||
<twig:ToolBarButton icon="search" text="Rechercher tout" action="search"/>
|
||||
<twig:ToolBarButton icon="user-plus" text="Importation manuelle" action="import"/>
|
||||
<twig:Divider/>
|
||||
<twig:ToolBarButton icon="wrench" text="Modifier Mangas" action="editMangas"/>
|
||||
|
||||
{% endset %}
|
||||
|
||||
{% set right_group %}
|
||||
<twig:ToolBarButton icon="th-large" text="Options" action="showOptions"/>
|
||||
<twig:DropdownMenu
|
||||
icon="eye"
|
||||
text="Vue"
|
||||
items="{{ toolbarItems.viewOptions }}"
|
||||
/>
|
||||
<twig:Divider/>
|
||||
<twig:DropdownMenu
|
||||
icon="sort"
|
||||
text="Trier"
|
||||
items="{{ toolbarItems.sortItems }}"
|
||||
/>
|
||||
<twig:DropdownMenu
|
||||
icon="filter"
|
||||
text="Filtre"
|
||||
items="{{ toolbarItems.filterItems }}"
|
||||
/>
|
||||
{% endset %}
|
||||
|
||||
<twig:Toolbar
|
||||
left_group="{{ left_group }}"
|
||||
right_group="{{ right_group }}"
|
||||
data-action="click@window->toolbar#clickOutside"
|
||||
/>
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<div class="relative">
|
||||
|
||||
Reference in New Issue
Block a user