Commit Graph

138 Commits

Author SHA1 Message Date
d913be9d2a chore: bump version to 1.6.3 2026-03-18 21:44:37 +01:00
037ede2750 chore: bump version to 1.6.2 2026-03-18 21:36:44 +01:00
06a245d90a feat: add metadata provider filter to series page
- Add `metadata_provider` query param to series API endpoints (linked/unlinked/specific provider)
- Return `metadata_provider` field in series response
- Add metadata filter dropdown on series page with all provider options
- Show small provider icon badge on linked series cards
- LiveSearchForm now wraps filters on two rows when needed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 21:35:38 +01:00
63d5fcaa13 chore: bump version to 1.6.1 2026-03-18 21:19:38 +01:00
020cb6baae feat: make series names clickable in batch metadata report
Links series names to their detail page where the metadata search
modal can be triggered for quick provider lookup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 21:07:21 +01:00
6db8042ffe chore: bump version to 1.6.0 2026-03-18 19:39:10 +01:00
d4f87c4044 feat: add i18n support (FR/EN) to backoffice with English as default
Implement full internationalization for the Next.js backoffice:
- i18n infrastructure: type-safe dictionaries (fr.ts/en.ts), cookie-based locale detection, React Context for client components, server-side translation helper
- Language selector in Settings page (General tab) with cookie + DB persistence
- All ~35 pages and components translated via t() / useTranslation()
- Default locale set to English, French available via settings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 19:39:01 +01:00
055c376222 fix: complete French translation for settings page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 18:26:59 +01:00
1cc5d049ea chore: bump version to 1.5.6 2026-03-18 18:26:50 +01:00
b955c2697c feat: add batch metadata jobs, series filters, and translate backoffice to French
- Add metadata_batch job type with background processing via tokio::spawn
- Auto-apply metadata only when single result at 100% confidence
- Support primary + fallback provider per library, "none" to opt out
- Add batch report/results API endpoints and job detail UI
- Add series_status and has_missing filters to both series listing pages
- Add GET /series/statuses endpoint for dynamic filter options
- Normalize series_metadata status values (migration 0036)
- Hide ComicVine provider tab when no API key configured
- Translate entire backoffice UI from English to French

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 18:26:44 +01:00
9a8c1577af chore: bump version to 1.5.5 2026-03-18 16:11:08 +01:00
52b9b0e00e feat: add series status, improve providers & e2e tests
- Add series status concept (ongoing/ended/hiatus/cancelled/upcoming)
  with normalization across all providers
- Add status field to series_metadata table (migration 0033)
- AniList: use chapters as fallback for volume count on ongoing series,
  add books_message when both volumes and chapters are null
- Bedetheque: extract description from meta tag, genres, parution status,
  origin/language; rewrite book parsing with itemprop microdata for
  clean ISBN, dates, page counts, covers; filter placeholder authors
- Add comprehensive e2e provider tests with field coverage reporting
- Wire status into EditSeriesForm, MetadataSearchModal, and series page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 16:10:45 +01:00
51ef2fa725 chore: bump version to 1.5.4 2026-03-18 15:27:29 +01:00
7d53babc84 chore: bump version to 1.5.3 2026-03-18 15:23:54 +01:00
1a91c051b5 chore: bump version to 1.5.2 2026-03-18 15:16:21 +01:00
48ca9d0a8b chore: bump version to 1.5.1 2026-03-18 15:12:44 +01:00
ac13f53124 chore: bump version to 1.5.0 2026-03-18 15:03:49 +01:00
c9ccf5cd90 feat: add external metadata sync system with multiple providers
Add a complete metadata synchronization system allowing users to search
and sync series/book metadata from external providers (Google Books,
Open Library, ComicVine, AniList, Bédéthèque). Each library can use a
different provider. Matching requires manual approval with detailed sync
reports showing what was updated or skipped (locked fields protection).

Key changes:
- DB migrations: external_metadata_links, external_book_metadata tables,
  library metadata_provider column, locked_fields, total_volumes, book
  metadata fields (summary, isbn, publish_date)
- Rust API: MetadataProvider trait + 5 provider implementations,
  7 metadata endpoints (search, match, approve, reject, links, missing,
  delete), sync report system, provider language preference support
- Backoffice: MetadataSearchModal, ProviderIcon, SafeHtml components,
  settings UI for provider/language config, enriched book detail page,
  edit forms with locked fields support, API proxy routes
- OpenAPI/Swagger documentation for all new endpoints and schemas

Closes #3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 14:59:24 +01:00
389d71b42f refactor: replace Meilisearch with PostgreSQL full-text search
Remove Meilisearch dependency entirely. Search is now handled by
PostgreSQL ILIKE with pg_trgm indexes, joining series_metadata for
series-level authors. No external search engine needed.

- Replace search.rs Meilisearch HTTP calls with PostgreSQL queries
- Remove meili.rs from indexer, sync_meili call from job pipeline
- Remove MEILI_URL/MEILI_MASTER_KEY from config, state, env files
- Remove meilisearch service from docker-compose.yml
- Add migration 0027: drop sync_metadata, enable pg_trgm, add indexes
- Remove search resync button/endpoint (no longer needed)
- Update all documentation (CLAUDE.md, README.md, AGENTS.md, PLAN.md)

API contract unchanged — same SearchResponse shape returned.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:59:25 +01:00
2985ef5561 chore: bump version to 1.4.0 2026-03-18 10:59:12 +01:00
4be8177683 feat: fix author search, add edit modals, settings tabs & search resync
- Fix Meilisearch indexing to use authors[] array instead of scalar author field
- Join series_metadata to include series-level authors in search documents
- Configure searchable attributes (title, authors, series) in Meilisearch
- Convert EditSeriesForm and EditBookForm from inline forms to modals
- Add tabbed navigation (General / Integrations) to Settings page
- Add Force Search Resync button (POST /settings/search/resync)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:45:36 +01:00
a675dcd2a4 chore: bump version to 1.3.0 2026-03-18 10:45:16 +01:00
127cd8a42c feat(komga): add Komga read-status sync with reports and history
Adds Komga sync feature to import read status from a Komga server.
Books are matched by title (case-insensitive) with series+title primary
match and title-only fallback. Sync reports are persisted with matched,
newly marked, and unmatched book lists. UI shows check icon for newly
marked books, sorted to top. Credentials (URL+username) are saved
between sessions. Uses HashSet for O(1) lookups to handle large libraries.

Closes #2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:04:19 +01:00
1b9f2d3915 chore: bump version to 1.2.2 2026-03-16 22:04:04 +01:00
f095bf050b chore: bump version to 1.2.1 2026-03-16 21:12:25 +01:00
5c3ddf7819 chore: bump version to 1.2.0 2026-03-16 19:29:43 +01:00
c56d02a895 chore: bump version to 1.1.0 2026-03-16 19:29:24 +01:00
bc98067871 feat(books): édition des métadonnées livres et séries + champ authors multi-valeurs
- Nouveaux endpoints PATCH /books/:id et PATCH /libraries/:id/series/:name pour éditer les métadonnées
- GET /libraries/:id/series/:name/metadata pour récupérer les métadonnées de série
- Ajout du champ `authors` (Vec<String>) sur les structs Book/BookDetails
- 3 migrations : table series_metadata, colonne authors sur series_metadata et books
- Composants EditBookForm et EditSeriesForm dans le backoffice
- Routes API Next.js correspondantes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 17:21:55 +01:00
9fbdf793d0 chore: bump version to 1.0.1 2026-03-16 12:08:15 +01:00
44c6dd626a feat(backoffice): afficher le format (cbz/cbr/pdf) au lieu du kind sur les cards
- Ajoute `format: string | null` dans BookDto
- BookCard et page détail utilisent `book.format ?? book.kind` avec les couleurs
  success=CBZ, warning=CBR, destructive=PDF

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 08:09:26 +01:00
e18bbba4ce feat: add sort parameter (title/latest) to books and series endpoints
Add sort=latest option to GET /books and GET /series API endpoints,
and expose a Sort select in the backoffice books and series pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 21:46:37 +01:00
2870dd9dbc chore: bump version to 1.0.0 2026-03-15 18:38:01 +01:00
cf2e7a0be7 feat(backoffice): add dashboard statistics with charts
Add GET /stats API endpoint with collection overview, reading status,
format/library breakdowns, top series, and monthly additions.
Replace static home page with interactive dashboard featuring donut
charts, bar charts, and progress bars. Use distinct colors for series
(warning/yellow) across nav, page titles, and quick links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 18:37:53 +01:00
82444cda02 chore: bump version to 0.3.0 2026-03-15 18:17:27 +01:00
1d25c8869f feat(backoffice): add reading progress management, series page, and live search
- API: add POST /series/mark-read to batch mark all books in a series
- API: add GET /series cross-library endpoint with search, library and status filters
- API: add library_id to SeriesItem response
- Backoffice: mark book as read/unread button on book detail page
- Backoffice: mark series as read/unread button on series cards
- Backoffice: new /series top-level page with search and filters
- Backoffice: new /libraries/[id]/series/[name] series detail page
- Backoffice: opacity on fully read books and series cards
- Backoffice: live search with debounce on books and series pages
- Backoffice: reading status filter on books and series pages
- Fix $2 -> $1 parameter binding in mark-series-read SQL

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 18:17:16 +01:00
673777bc8d chore: bump version to 0.2.0 2026-03-15 16:23:09 +01:00
03af82d065 feat(tokens): allow permanent deletion of revoked tokens
Add POST /admin/tokens/{id}/delete endpoint that permanently removes
a token from the database (only if already revoked). Add delete button
in backoffice UI for revoked tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 15:19:44 +01:00
78e28a269d chore: bump version to 0.1.5 2026-03-15 15:17:16 +01:00
96d9efdeed chore: bump version to 0.1.4 2026-03-15 13:20:41 +01:00
9f5183848b chore: bump version to 0.1.3 2026-03-15 13:09:53 +01:00
6f9dd108ef chore: bump version to 0.1.2 2026-03-15 13:06:36 +01:00
c7f3ad981d chore: bump version to 0.1.1 2026-03-15 12:51:54 +01:00
0d60d46cae feat(indexer,backoffice): logs par domaine, réduction fd, UI mobile
- Ajout de targets de log par domaine (scan, extraction, thumbnail, watcher)
  contrôlables via RUST_LOG pour activer/désactiver les logs granulaires
- Ajout de logs détaillés dans extracting_pages (per-book timing en debug,
  progression toutes les 25 books en info)
- Réduction de la consommation de fd: walkdir max_open(20/10), comptage
  séquentiel au lieu de par_iter parallèle, suppression de rayon
- Détection ENFILE dans le scanner: abort après 10 erreurs IO consécutives
- Backoffice: settings dans le burger mobile, masquer "backoffice" et
  icône settings en mobile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 11:57:49 +01:00
6947af10fe perf(api,indexer): optimiser pages, thumbnails, watcher et robustesse fd
- Pages: mode Original (zero-transcoding), ETag/304, cache index CBZ,
  préfetch next 2 pages, filtre Triangle par défaut
- Thumbnails: DCT scaling JPEG via jpeg-decoder (decode 7x plus rapide),
  img.thumbnail() pour resize, support format Original, fix JPEG RGBA8
- API fallback thumbnail: OutputFormat::Original + DCT scaling au lieu
  de WebP full-decode, retour (bytes, content_type) dynamique
- Watcher: remplacement notify par poll léger sans inotify/fd,
  skip poll quand job actif, snapshots en mémoire
- Jobs: mutex exclusif corrigé (tous statuts actifs, tous types exclusifs)
- Robustesse: suppression fs::canonicalize (problèmes fd Docker),
  list_folders avec erreurs explicites, has_children default true
- Backoffice: FormRow items-start pour alignement inputs avec helper text,
  labels settings clarifiés

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 23:07:42 +01:00
fe54f55f47 feat(indexer,backoffice): ajouter warnings dans les stats de job, skip fichiers inaccessibles
- Indexer: ajout du champ `warnings` dans JobStats pour les erreurs
  non-fatales (fichiers inaccessibles, permissions)
- Indexer: skip les fichiers dont le stat échoue au lieu de faire
  crasher tout le scan de la library
- Backoffice: affichage des warnings dans le détail job (summary,
  timeline, Index Statistics) et dans la popin jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:44:48 +01:00
7cca7e40c2 fix(parsers,api,indexer,backoffice): corriger CBZ Unicode extra fields, centraliser extraction, nettoyer Meili, fixer header
- Parsers: raw ZIP reader (flate2) contournant la validation CRC32 des
  Unicode extra fields (0x7075) qui bloquait certains CBZ
- Parsers: nouvelle API publique extract_page() pour extraire une page
  par index depuis CBZ/CBR/PDF avec fallbacks automatiques
- API: suppression du code d'extraction dupliqué, délégation à parsers::extract_page()
- API: retrait des dépendances directes zip/unrar/pdfium-render/natord
- Indexer: nettoyage Meili systématique à chaque sync (au lieu de ~10%)
  avec pagination pour supporter les grosses collections — corrige les
  doublons dans la recherche
- Indexer: retrait de la dépendance rand (plus utilisée)
- Backoffice: popin jobs rendue via createPortal avec positionnement
  dynamique — corrige le débordement desktop et le header cassé en mobile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:26:14 +01:00
358896c7d5 perf(indexer): éliminer le pre-count WalkDir en mode incrémental + concurrence adaptative
- Incremental rebuild: remplace le WalkDir de comptage par un COUNT(*) SQL
  → incrémental 67s → 25s (-62%) sur disque externe
- Full rebuild: conserve le WalkDir (DB vidée avant le comptage)
- Concurrence par défaut: num_cpus/2 clampé [2,8] au lieu de 2 fixe
- Ajoute num_cpus comme dépendance workspace
- Backoffice jobs: un seul formulaire avec formAction par bouton (icônes rétablies)
- infra/perf.sh: corrige l'endpoint /index/jobs/:id (pas /details), exporte BASE_API/TOKEN

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 22:15:41 +01:00
1d10044d46 fix: plusieurs correctifs jobs et analyzer
- cancel_job: ajouter 'extracting_pages' aux statuts annulables
- cleanup_stale_jobs: couvrir 'extracting_pages' et 'generating_thumbnails' au redémarrage
- analyzer: ne pas régénérer le thumbnail si déjà existant (skip sub-phase B)
- analyzer: supprimer les dotfiles macOS (._*) encore en DB
- SSE backoffice: réduire le spam de logs en cas d'API injoignable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 21:41:52 +01:00
3bd2fb7c1f feat(jobs): introduce extracting_pages status and update job progress handling
- Added a new job status 'extracting_pages' to represent the first sub-phase of thumbnail generation.
- Updated the database schema to include a timestamp for when thumbnail generation starts.
- Enhanced job progress components to handle the new status, including UI updates for displaying progress and status labels.
- Refactored job-related logic to accommodate the two-phase process: extracting pages and generating thumbnails.
- Adjusted SQL queries and job detail responses to include the new fields and statuses.

This change improves the clarity of job processing states and enhances user feedback during the thumbnail generation process.
2026-03-11 17:50:48 +01:00
1c106a4ff2 fix(db): ajouter 'cancelled' à la contrainte CHECK de index_jobs.status
La contrainte index_jobs_status_check ne listait pas 'cancelled', ce qui
causait une erreur 500 à chaque tentative d'annulation de job.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 15:58:03 +01:00