diff --git a/assets/controllers/toolbar_controller.js b/assets/controllers/toolbar_controller.js
index e4eeadd..00f5526 100644
--- a/assets/controllers/toolbar_controller.js
+++ b/assets/controllers/toolbar_controller.js
@@ -5,55 +5,79 @@ export default class extends Controller {
static targets = ["dropdown"]
static values = {
currentSort: String,
- currentOrder: String
+ currentOrder: String,
+ currentStatus: String
}
- refresh() {
- console.log("Refreshing...")
+ refreshMetadata() {
+ console.log("Refreshing...");
}
- syncRss() {
- console.log("Syncing RSS...")
- }
-
- search() {
- console.log("Searching...")
+ searchLastChapter() {
+ console.log("Searching last chapter...");
}
import() {
- console.log("Importing...")
+ console.log("Importing...");
}
editMangas() {
- console.log("Editing mangas...")
+ console.log("Editing mangas...");
+ }
+
+ editManga() {
+ console.log("Editing manga...");
+ }
+
+ deleteMangas() {
+ console.log("Deleting mangas...");
+ }
+
+ deleteManga() {
+ console.log("Deleting manga...");
}
showOptions() {
- console.log("Showing options...")
+ console.log("Showing options...");
}
- changeView() {
- console.log("Changing view...")
+ changeView(event) {
+ event.preventDefault();
+ const viewOption = event.currentTarget.dataset.view;
+
+ const url = new URL(window.location);
+ url.searchParams.set('view', viewOption);
+
+ window.location = url.toString();
}
sort(event) {
event.preventDefault()
- const sortOption = event.currentTarget.dataset.sortOption
- let order = 'asc'
+ const sortOption = event.currentTarget.dataset.sort;
+ let order = 'asc';
if (sortOption === this.currentSortValue && this.currentOrderValue === 'asc') {
- order = 'desc'
+ order = 'desc';
}
- const url = new URL(window.location)
- url.searchParams.set('sort', sortOption)
- url.searchParams.set('order', order)
+ const url = new URL(window.location);
+ url.searchParams.set('sort', sortOption);
+ url.searchParams.set('order', order);
- window.location = url.toString()
+ window.location = url.toString();
}
- filter() {
- console.log("Filtering...")
+ filter(event) {
+ event.preventDefault();
+ const filterOption = event.currentTarget.dataset.filter;
+
+ const url = new URL(window.location);
+ url.searchParams.set('status', filterOption);
+
+ // Réinitialiser la page à 1 si on utilise la pagination
+ // url.searchParams.set('page', '1');
+
+ window.location = url.toString();
}
}
diff --git a/src/Controller/ImportController.php b/src/Controller/ImportController.php
index 6996d4d..55219df 100644
--- a/src/Controller/ImportController.php
+++ b/src/Controller/ImportController.php
@@ -33,7 +33,7 @@ class ImportController extends AbstractController
}
- #[Route('/import', name: 'app_import')]
+ #[Route('/manga/import', name: 'app_manga_import')]
public function index(Request $request, SessionInterface $session): Response
{
if ($request->isMethod('post')) {
@@ -73,7 +73,7 @@ class ImportController extends AbstractController
$filePath = $session->get('import_file_path');
$originalFileName = $session->get('import_original_file_name');
if (!$filePath || !$originalFileName) {
- return $this->redirectToRoute('app_import');
+ return $this->redirectToRoute('app_manga_import');
}
$metadata = $this->cbzService->extractMetadata($filePath, $originalFileName);
@@ -82,7 +82,7 @@ class ImportController extends AbstractController
'type' => 'error',
'message' => 'Impossible de détecter le titre du manga.'
]);
- return $this->redirectToRoute('app_import');
+ return $this->redirectToRoute('app_manga_import');
}
$mangas = $this->mangaRepository->findBySlug($metadata['title']);
@@ -130,7 +130,7 @@ class ImportController extends AbstractController
public function confirm(Request $request, SessionInterface $session): Response
{
if (!$request->isMethod('POST')) {
- return $this->redirectToRoute('app_import');
+ return $this->redirectToRoute('app_manga_import');
}
$action = $request->request->get('action');
@@ -145,7 +145,7 @@ class ImportController extends AbstractController
'type' => 'error',
'message' => 'Manga non trouvé.'
]);
- return $this->redirectToRoute('app_import');
+ return $this->redirectToRoute('app_manga_import');
}
$filePath = $session->get('import_file_path');
@@ -154,7 +154,7 @@ class ImportController extends AbstractController
'type' => 'error',
'message' => 'Fichier d\'import non trouvé.'
]);
- return $this->redirectToRoute('app_import');
+ return $this->redirectToRoute('app_manga_import');
}
$originalFileName = $session->get('import_original_file_name');
@@ -192,6 +192,6 @@ class ImportController extends AbstractController
]);
}
- return $this->redirectToRoute('app_import');
+ return $this->redirectToRoute('app_manga_import');
}
}
diff --git a/src/Controller/MangaController.php b/src/Controller/MangaController.php
index 0629ffc..5e29666 100644
--- a/src/Controller/MangaController.php
+++ b/src/Controller/MangaController.php
@@ -4,6 +4,7 @@ namespace App\Controller;
use App\Entity\Chapter;
use App\Entity\Manga;
+use App\Manager\Toolbar\Factory\ToolbarFactory;
use App\Manager\ToolbarManager;
use App\Message\DownloadChapter;
use App\Repository\ChapterRepository;
@@ -36,7 +37,7 @@ class MangaController extends AbstractController
private readonly MangaUpdatesMetadataProvider $mangaUpdatesDbProvider,
private readonly MessageBusInterface $bus,
private readonly CbzService $cbzService,
- private readonly ToolbarManager $toolbarManager
+ private readonly ToolbarFactory $toolbarFactory
)
{
}
@@ -46,12 +47,16 @@ class MangaController extends AbstractController
{
$sort = $request->query->get('sort', 'title');
$order = $request->query->get('order', 'asc');
+ $status = $request->query->get('status', 'all');
+ $view = $request->query->get('view', 'poster');
- $mangas = $this->mangaRepository->findAllSorted($sort, $order);
+ $mangas = $this->mangaRepository->findAllSortedAndFiltered($sort, $order, $status);
return $this->render('manga/index.html.twig', [
'mangas' => $mangas,
- 'toolbarItems' => $this->toolbarManager->getToolbarItems(),
+ 'toolbar' => $this->toolbarFactory->createToolbar('manga_list')->getGroups(),
+ 'currentStatus' => $status,
+ 'currentView' => $view,
]);
}
@@ -94,7 +99,7 @@ class MangaController extends AbstractController
return $this->render('manga/show_chapters.html.twig', [
'chapters_by_volume' => $chaptersByVolume,
'manga' => $manga,
- 'toolbarItems' => $this->toolbarManager->getToolbarItems(),
+ 'toolbar' => $this->toolbarFactory->createToolbar('chapter_list')->getGroups(),
]);
}
diff --git a/src/Manager/Toolbar/Definition/ChapterListToolbar.php b/src/Manager/Toolbar/Definition/ChapterListToolbar.php
new file mode 100644
index 0000000..a075e7d
--- /dev/null
+++ b/src/Manager/Toolbar/Definition/ChapterListToolbar.php
@@ -0,0 +1,21 @@
+addToLeftGroup(new ToolbarButton('keyboard', 'Rename chapters', 'renameChapters'))
+ ->addToLeftGroup(new ToolbarButton('file-zipper', 'Manage cbz', 'manageCbz'))
+ ->addToLeftGroup(new ToolbarButton('history', 'History', 'history'))
+ ->addToLeftGroup(new ToolbarDivider())
+ ->addToLeftGroup(new ToolbarButton('bookmark', 'Monitoring', 'monitoring'))
+ ->addToLeftGroup(new ToolbarButton('wrench', 'Edit', 'edit'))
+ ->addToLeftGroup(new ToolbarButton('trash-can', 'Delete', 'delete'))
+ ->addToRightGroup(new ToolbarButton('chevron-down', 'Expand all', 'expandAll'));
+ }
+}
diff --git a/src/Manager/Toolbar/Definition/MangaListToolbar.php b/src/Manager/Toolbar/Definition/MangaListToolbar.php
new file mode 100644
index 0000000..63ebf16
--- /dev/null
+++ b/src/Manager/Toolbar/Definition/MangaListToolbar.php
@@ -0,0 +1,37 @@
+addToLeftGroup(new ToolbarButton('arrows-rotate', 'Refresh metadata', 'refreshMetadata'))
+ ->addToLeftGroup(new ToolbarButton('search', 'Search last chapter', 'searchLastChapter'))
+ ->addToLeftGroup(new ToolbarDivider())
+ ->addToLeftGroup(new ToolbarButton('plus', 'Add Manga', 'addManga'))
+
+ ->addToRightGroup(new ToolbarButton('th-large', 'Options', 'options'))
+ ->addToRightGroup(new ToolbarDivider())
+ ->addToRightGroup(new ToolbarDropdown('eye', 'View', 'changeView', [
+ ['text' => 'Poster View', 'action' => 'changeView', 'data' => ['view' => 'poster']],
+ ['text' => 'Table View', 'action' => 'changeView', 'data' => ['view' => 'table']],
+ ['text' => 'Resume View', 'action' => 'changeView', 'data' => ['view' => 'resume']]
+ ]))
+ ->addToRightGroup(new ToolbarDropdown('sort', 'Sort', 'sort', [
+ ['text' => 'Par titre', 'action' => 'sort', 'data' => ['sort' => 'title']],
+ ['text' => 'Par année de publication', 'action' => 'sort', 'data' => ['sort' => 'publicationYear']],
+ ['text' => 'Par date d\'ajout', 'action' => 'sort', 'data' => ['sort' => 'createdAt']]
+ ]))
+ ->addToRightGroup(new ToolbarDropdown('filter', 'Filter', 'filter', [
+ ['text' => 'Tous les mangas', 'action' => 'filter', 'data' => ['filter' => 'all']],
+ ['text' => 'Mangas en cours', 'action' => 'filter', 'data' => ['filter' => 'ongoing']],
+ ['text' => 'Mangas terminés', 'action' => 'filter', 'data' => ['filter' => 'completed']]
+ ]))
+ ;
+ }
+}
diff --git a/src/Manager/Toolbar/Definition/Toolbar.php b/src/Manager/Toolbar/Definition/Toolbar.php
new file mode 100644
index 0000000..4bf64bf
--- /dev/null
+++ b/src/Manager/Toolbar/Definition/Toolbar.php
@@ -0,0 +1,31 @@
+leftGroup[] = $element;
+ return $this;
+ }
+
+ public function addToRightGroup(ToolbarElement $element): self
+ {
+ $this->rightGroup[] = $element;
+ return $this;
+ }
+
+ public function getGroups(): array
+ {
+ return [
+ 'leftGroup' => $this->leftGroup,
+ 'rightGroup' => $this->rightGroup,
+ ];
+ }
+}
diff --git a/src/Manager/Toolbar/Element/AbstractToolbarElement.php b/src/Manager/Toolbar/Element/AbstractToolbarElement.php
new file mode 100644
index 0000000..f47de3d
--- /dev/null
+++ b/src/Manager/Toolbar/Element/AbstractToolbarElement.php
@@ -0,0 +1,37 @@
+icon = $icon;
+ $this->text = $text;
+ $this->action = $action;
+ }
+
+ public function getIcon(): string
+ {
+ return $this->icon;
+ }
+
+ public function getText(): string|array
+ {
+ return $this->text;
+ }
+
+ public function getAction(): string
+ {
+ return $this->action;
+ }
+
+ public function getAdditionalProperties(): array
+ {
+ return [];
+ }
+}
diff --git a/src/Manager/Toolbar/Element/ToolbarButton.php b/src/Manager/Toolbar/Element/ToolbarButton.php
new file mode 100644
index 0000000..ac7c40b
--- /dev/null
+++ b/src/Manager/Toolbar/Element/ToolbarButton.php
@@ -0,0 +1,14 @@
+items = $items;
+ }
+
+ public function getType(): string
+ {
+ return 'dropdown';
+ }
+
+ public function getAdditionalProperties(): array
+ {
+ return ['items' => $this->items];
+ }
+}
diff --git a/src/Manager/Toolbar/Element/ToolbarElement.php b/src/Manager/Toolbar/Element/ToolbarElement.php
new file mode 100644
index 0000000..db3bcd4
--- /dev/null
+++ b/src/Manager/Toolbar/Element/ToolbarElement.php
@@ -0,0 +1,12 @@
+ new MangaListToolbar(),
+ 'chapter_list' => new ChapterListToolbar(),
+ default => throw new \InvalidArgumentException("Unknown toolbar type: $type"),
+ };
+ }
+}
diff --git a/src/Manager/ToolbarManager.php b/src/Manager/ToolbarManager.php
index 0693638..4c2ff30 100644
--- a/src/Manager/ToolbarManager.php
+++ b/src/Manager/ToolbarManager.php
@@ -25,17 +25,18 @@ class ToolbarManager
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']]
+ ['text' => 'Tous les mangas', 'action' => 'filter', 'data' => ['filter-option' => 'all']],
+ ['text' => 'Mangas en cours', 'action' => 'filter', 'data' => ['filter-option' => 'ongoing']],
+ ['text' => 'Mangas terminés', 'action' => 'filter', 'data' => ['filter-option' => 'completed']]
];
}
private function getViewOptions(): array
{
return [
- ['text' => 'Vue grille', 'action' => 'changeView', 'data' => ['view-option' => 'grid']],
- ['text' => 'Vue liste', 'action' => 'changeView', 'data' => ['view-option' => 'list']]
+ ['text' => 'Vue poster', 'action' => 'changeView', 'data' => ['view-option' => 'poster']],
+ ['text' => 'Vue résumé', 'action' => 'changeView', 'data' => ['view-option' => 'resume']],
+ ['text' => 'Vue table', 'action' => 'changeView', 'data' => ['view-option' => 'table']]
];
}
}
diff --git a/src/Repository/MangaRepository.php b/src/Repository/MangaRepository.php
index 29fce6b..b4930a2 100644
--- a/src/Repository/MangaRepository.php
+++ b/src/Repository/MangaRepository.php
@@ -103,23 +103,14 @@ class MangaRepository extends ServiceEntityRepository
return $query->getQuery()->getOneOrNullResult();
}
- public function findAllSorted(string $sort = 'title', string $order = 'asc'): array
+ public function findAllSortedAndFiltered($sort = 'title', $order = 'asc', $status = 'all')
{
- $qb = $this->createQueryBuilder('m');
+ $qb = $this->createQueryBuilder('m')
+ ->orderBy('m.' . $sort, $order);
- 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');
+ if ($status !== 'all') {
+ $qb->andWhere('m.status = :status')
+ ->setParameter('status', $status);
}
return $qb->getQuery()->getResult();
diff --git a/src/Service/MangadexProvider.php b/src/Service/MangadexProvider.php
index 3fd5896..7994b27 100644
--- a/src/Service/MangadexProvider.php
+++ b/src/Service/MangadexProvider.php
@@ -42,6 +42,7 @@ readonly class MangadexProvider implements MetadataProviderInterface
->setSlug($this->slugger->slug($result['attributes']['title']['en'])->lower())
->setDescription($result['attributes']['description']['fr'] ?? $result['attributes']['description']['en'] ?? '')
->setPublicationYear($result['attributes']['year'])
+ ->setStatus($result['attributes']['status'])
;
$tags = [];
foreach($result['attributes']['tags'] as $tag){
diff --git a/templates/activity/index.html.twig b/templates/activity/index.html.twig
index af2dd64..caf457e 100644
--- a/templates/activity/index.html.twig
+++ b/templates/activity/index.html.twig
@@ -1,41 +1,8 @@
{% extends 'base.html.twig' %}
{% block toolbar %}
- {% set left_group %}
-
{{ manga.publicationYear }}
+ {% if currentView == 'poster' %} + {# Vue poster actuelle #} +{{ manga.publicationYear }}
+Added: {{ manga.createdAt|date('M d, Y') }}
Added: {{ manga.createdAt|date('M d, Y') }}
Aucun manga trouvé.
- {% endfor %} -Aucun manga trouvé.
+ {% endfor %} +{{ manga.publicationYear }}
+{{ manga.description|truncate(200) }}
+Added: {{ manga.createdAt|date('M d, Y') }}
+Aucun manga trouvé.
+ {% endfor %} +| Manga Title | + {#Volumes | #} +Chapters | +|||
|---|---|---|---|---|---|
|
+
+ {{ manga.title }}
+
+ |
+ {# #} + {# {{ manga.volumes|length }} #} + {# | #} +
+ {% set total_chapters = manga.chapters|length %}
+ {% set available_chapters = manga.chapters|filter(chapter => chapter.cbzPath is not null)|length %}
+
+
+
+
+
+ {{ available_chapters }} / {{ total_chapters }}
+ |
+ |||
| Aucun manga trouvé. | +|||||
| - + | @@ -169,7 +140,8 @@ data-url="{{ path('add_chapter', {id: chapter.id}) }}" > - + {% else %} @@ -179,7 +151,8 @@ {% endif %} - + diff --git a/templates/menu/menu.html.twig b/templates/menu/menu.html.twig index 78f1c05..36e9db0 100644 --- a/templates/menu/menu.html.twig +++ b/templates/menu/menu.html.twig @@ -9,7 +9,7 @@ {% if app.request.get('_route') starts with 'app_manga' %} {% endif %}