Commit Graph

31 Commits

Author SHA1 Message Date
yann64 d685c2211e CHANGELOG : correction des entrées 1.0.2 et 1.0.3 (correctifs partiels)
Les descriptions initiales présentaient ces versions comme des corrections
définitives alors qu'elles n'adressaient qu'une partie du problème.
Mention explicite du renvoi vers 1.0.4 pour le correctif complet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.0.4
2026-06-05 07:20:32 +02:00
yann64 a400b7cc66 Release 1.0.4 — changelog + bump version dev 1.0.5
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 07:17:51 +02:00
yann64 ed5cfcd275 Fix wizard : suppression totale des sous-processus exec() dans install()
- APP_KEY : généré directement en PHP (random_bytes) + écrit dans .env + propagé
  via config() et putenv() → évite le bug de pattern-matching de key:generate
  (la clé en mémoire ≠ clé dans le .env réécrit par writeEnv)
- DB_* + APP_KEY : putenv() écrase l'env OS hérité au boot (pgsql/temp-key) pour
  que tout sous-processus futur hérite des bonnes valeurs
- optimize supprimé de l'installation : config:cache re-boostrappe l'app via
  bootstrap/app.php dans un contexte où l'Encrypter peut lever MissingAppKeyException ;
  optimize:clear seul suffit — Laravel reconstruit ses caches à la première requête
- key:generate converti en Artisan::call() puis remplacé par génération PHP directe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 07:17:32 +02:00
yann64 4110caa25a Release 1.0.3 — changelog + bump version dev 1.0.4
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.0.3
2026-06-04 23:03:14 +02:00
yann64 9225abc804 Fix wizard : migrations via Artisan::call() pour éviter l'héritage d'env pgsql
Cause racine : public/index.php charge le .env auto-créé (pgsql) et appelle
putenv('DB_CONNECTION=pgsql'). Les sous-processus exec() héritent cet env OS.
phpdotenv en mode immutable refuse d'écraser une variable déjà définie →
le nouveau .env mysql est ignoré, la migration tente une connexion pgsql.

Fix : reconfiguration de la connexion BDD en mémoire via config() + DB::purge()
puis exécution des migrations via Artisan::call() dans le processus courant.
Plus aucun subprocess pour les migrations → aucun héritage d'env parasite.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:19:50 +02:00
yann64 56dbd8a0bf Setup : affichage du numéro de version dans l'assistant d'installation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:12:04 +02:00
yann64 79b831367c Release 1.0.2 — changelog + bump version dev 1.0.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.0.2
2026-06-04 22:04:55 +02:00
yann64 715aad58e1 Fix wizard : config:clear avant migrations pour éviter conflit pgsql/mysql
Sans ce clear, un bootstrap/cache/config.php résiduel (produit par
php artisan optimize en dev) est lu en priorité sur le .env réécrit
par writeEnv(), forçant une connexion pgsql même quand mysql est choisi.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:02:45 +02:00
yann64 c3e1d4378c Release 1.0.1 — changelog + bump version dev 1.0.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.0.1
2026-06-04 21:44:35 +02:00
yann64 5acc6ff5c8 Fix wizard : auto-création du .env minimal quand absent au démarrage
Sans .env, Laravel lève MissingAppKeyException avant que le moindre
middleware ou contrôleur ne s'exécute, rendant /setup inaccessible.

public/index.php génère maintenant un .env depuis .env.example avec
une APP_KEY temporaire (random_bytes 32) et force SESSION_DRIVER=file,
CACHE_STORE=file, QUEUE_CONNECTION=sync pour un boot sans base de données.
Le wizard remplace ce fichier lors de l'installation définitive.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:41:51 +02:00
yann64 2e6ac29e95 Ajout de public/servercheck.php (outil de diagnostic serveur)
Fichier autonome (sans dépendance Laravel) vérifiant :
- Version PHP (≥ 8.2)
- Extensions requises et optionnelles
- Directives php.ini (memory_limit, upload_max_filesize…)
- Répertoires accessibles en écriture (storage/, bootstrap/cache/)
- Présence des fichiers clés (.env, vendor, assets compilés)
- Test de connexion BDD (MySQL / PostgreSQL) via formulaire
Interface HTML auto-adaptative (dark mode OS), sans dépendance externe.

À exclure des archives de production (--exclude public/servercheck.php
dans le rsync de build-release).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:35:55 +02:00
yann64 a1860e9462 Page carte interactive des relevés (Leaflet + OpenStreetMap)
- CarteController : index() + data() (JSON) — requête lieux géolocalisés
  ayant des sources avec relevés, agrégats par lieu
- Lieu model : relations sources() et releves() (hasManyThrough)
- Vue carte/index.blade.php : carte Leaflet pleine hauteur, marqueurs
  colorés par nombre de sources (taille/couleur proportionnels),
  popup par lieu avec liste des sources, statuts, années et lien recherche
- Tuiles OpenStreetMap inversées en mode sombre
- Route GET /carte + GET /carte/data
- Lien "Carte" dans la navigation desktop et mobile
- @stack('head') dans le layout pour injecter Leaflet uniquement sur la page carte

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:02:28 +02:00
yann64 6f55663984 Fallback routing sans mod_rewrite via FallbackResource
Utilise mod_rewrite si disponible, sinon FallbackResource (Apache 2.2.16+,
aucun module supplémentaire requis) pour les hébergements mutualisés
qui n'ont pas mod_rewrite activé.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:30:36 +02:00
yann64 8efb7e30df README : correction de la procédure d'installation Docker
- Stack réelle : PHP-FPM + Nginx + PostgreSQL (pas de Redis en prod)
- Détail des 4 étapes : extraction, premier lancement, config .env, install finale
- Paramètres .env minimaux documentés (APP_KEY auto-généré, SMTP via UI admin)
- Commandes courantes (logs, shell, restart)
- Section mises à jour complète avec rollback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:16:23 +02:00
yann64 3faa74640d Fix dark mode : formulaires et composant lieu-picker
- app.css : règle @layer base globale pour tous les <input>, <select>,
  <textarea> en mode sombre (bg-gray-700, border-gray-600, text-gray-100)
  sans toucher checkboxes, radios ni boutons
- lieu-picker : bouton déclencheur, fenêtre modale, champ de recherche,
  liste de résultats et badges entièrement adaptés au thème sombre

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 20:14:44 +02:00
yann64 f530f55577 Mode sombre, option désactivation mises à jour, user-picker avec recherche
- Dark mode complet : darkMode:'class' Tailwind, sélecteur clair/sombre/auto
  dans la navigation (mémorisé dans localStorage, sans flash au chargement) ;
  53 vues et 8 composants Breeze mis à jour avec classes dark:
- Composant user-picker : fenêtre modale avec recherche temps réel (nom/email)
  remplace les <select> d'ajout de membres dans sections et sources
- Paramètres : option "Désactiver la vérification automatique des mises à jour"
  (case à cochage auto-soumise, route POST parametres/updates)
- Panneau "Paramètres généraux" remonté en tête de la page de paramètres
- README recentré sur l'installation manuelle hébergement PHP+MySQL
- VERSION 1.0.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 19:46:22 +02:00
yann64 07ab2a7063 Configuration SMTP et 2FA par code PIN e-mail
Paramètres du site :
- Nouvelle section "Serveur SMTP" avec host, port, chiffrement,
  identifiant, mot de passe, adresse/nom d'expéditeur
- Bouton "Envoyer un e-mail de test" (AJAX via Symfony EsmtpTransport) :
  tente la connexion + envoie un message réel à l'admin
- Badge "Configuré — 2FA actif" quand SMTP est en place
- Suppression de la configuration possible

Authentification 2FA :
- Si SMTP configuré : après validation identifiant/mot de passe,
  l'utilisateur est déconnecté, un PIN à 6 chiffres est généré,
  haché (bcrypt) et stocké en session, envoyé par e-mail (10 min)
- Page /2fa : saisie du PIN, bouton "Renvoyer le code", retour login
- Si l'envoi e-mail échoue : fallback sans 2FA (logue l'erreur)
- Si SMTP non configuré : login standard inchangé

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.0.0
2026-06-04 18:59:18 +02:00
yann64 e6f4d0c565 Fix logo navbar : contrainte max-height absolue sur l'image
Remplace le chaînage h-full (non fiable avec flex items-center)
par un max-height inline directement sur l'image : 40px max dans
une barre de 64px, centrée verticalement par le flex parent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:52:51 +02:00
yann64 b608501f39 Import/export CSV utilisateurs, filtre statut et titre du site modifiable
Utilisateurs :
- Filtre actif/inactif dans la liste (status=active|inactive)
- Export CSV avec les filtres actifs — séparateur ;, BOM UTF-8 (compatible Excel)
- Import CSV : détection auto du séparateur, validation ligne par ligne,
  mot de passe temporaire généré + affiché une seule fois dans les résultats
- Téléchargement d'un fichier modèle CSV

Paramètres du site :
- Champ "Titre du site" (site_name dans site_settings.json)
- Titre partagé via SiteSettingsService::siteName() et injecté dans config('app.name')
  au boot — s'applique partout sans modifier .env

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:48:36 +02:00
yann64 f341f822ab Affichage de la version dans la page Paramètres du site
Ajoute une section "Version du logiciel" dans admin/parametres avec :
- version installée + date d'installation
- bandeau de mise à jour disponible si nouvelle version détectée
- badge "À jour" si à jour (même logique que le tableau de bord admin)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:43:34 +02:00
yann64 caf7ad7fe2 Ajout de l'assistant d'installation web et corrections de navigation
- Wizard d'installation en 5 étapes (/setup) : prérequis PHP, base de données
  (PostgreSQL/MySQL avec test de connexion AJAX), paramètres app, compte admin,
  résultat — génère le .env, migre et crée l'administrateur
- CheckInstallation middleware : redirige vers /setup si non installé,
  protège /setup si déjà installé ; storage/installed comme marqueur
- Menu Administration : remplacé par le composant x-dropdown Breeze (même
  positionnement que le menu utilisateur — corrige le débordement en haut)
- Logo navbar : adaptatif via h-full/py-1.5 (s'adapte à la hauteur de la barre)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:39:55 +02:00
yann64 236d37976c Compatibilité MySQL + suppression de Redis comme dépendance requise
DbCompat (app/Support/DbCompat.php) :
- like()           → ilike (pgsql) ou like (mysql)
- jsonRegexRaw()   → data::text ~* ? (pgsql) ou CAST(data AS CHAR) REGEXP ? (mysql)
- ftsRaw()         → to_tsvector/plainto_tsquery (pgsql) ou null/fallback LIKE (mysql)
- generatedJsonCol()       → syntaxe colonne générée JSON selon le SGBD
- generatedJsonNestedCol() → idem pour champs imbriqués

Migrations :
- create_releves_table : JSON/JSONB selon SGBD, colonnes générées adaptées,
  index GIN uniquement pour PostgreSQL

Controllers :
- LieuController (search + index) : ilike → DbCompat::like()
- Admin\UserController (index)     : ilike → DbCompat::like()
- RechercheController              : FTS + regex → DbCompat, fallback LIKE MySQL
- ExportController                 : regex → DbCompat::jsonRegexRaw()

UpdateService :
- backupDatabase()  : pg_dump (pgsql) ou mysqldump (mysql)
- restoreBackup()   : psql (pgsql) ou mysql (mysql)

Docker :
- docker-compose.yml       : suppression Redis (plus requis)
- docker-compose.mysql.yml : nouveau fichier pour dev MySQL
- docker-compose.prod.yml  : suppression Redis, DB_IMAGE configurable,
  CACHE_STORE/SESSION_DRIVER/QUEUE_CONNECTION → database par défaut

.env.example :
- DB_PORT commenté avec les deux valeurs (5432/3306)
- CACHE_STORE et QUEUE_CONNECTION commentés (database par défaut)
- Redis marqué optionnel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:13:42 +02:00
yann64 f57ae068b9 Logo du site, favicon et contrôle des inscriptions
SiteSettingsService : persistance JSON dans storage/app/site_settings.json
  (pas de migration DB — survit aux mises à jour sans table supplémentaire)

Logo :
- Upload admin (PNG/JPG/SVG/WebP, max 2 Mo) → storage/app/public/site/logo.{ext}
- Favicon <link rel="icon"> injecté dans app.blade.php et guest.blade.php
- Logo affiché dans la barre de navigation (h-8, object-contain)
- Logo affiché sur la page de connexion (guest layout)
- Page d'accueil welcome.blade.php entièrement refaite : logo + bouton connexion
  (remplacement du template Laravel par défaut)
- Suppression du logo possible depuis Admin > Paramètres du site

Inscriptions :
- Désactivées par défaut (registration_enabled=false dans site_settings.json)
- RegisteredUserController : redirige vers /login si inscription désactivée
  (GET /register → redirect + message ; POST /register → abort 403)
- Page d'accueil : bouton "Créer un compte" masqué si inscriptions désactivées
- Admin > Paramètres du site : toggle checkbox pour activer/désactiver

AppServiceProvider : partage $siteLogoUrl et $registrationEnabled avec toutes les vues

Navigation : lien "Paramètres du site" en bas du menu Administration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 18:01:38 +02:00
yann64 cd9cc94895 i18n: traduction complète de la page profil en français
- Titre : "Mon profil"
- Informations du profil : Nom, Adresse e-mail, vérification e-mail
- Changer le mot de passe : Mot de passe actuel / Nouveau / Confirmer
- Supprimer le compte : textes + modale de confirmation + boutons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:54:19 +02:00
yann64 8fb7ee9fa4 fix: dropdown Administration et raccourcis tableau de bord admin
- Ajout de `relative` sur le conteneur du menu Administration +
  `top-full left-0` sur le dropdown (position correcte sous le bouton)
- Grille de raccourcis dans le tableau de bord admin : Utilisateurs,
  Sections, Types de sources, Types de lieux

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:53:29 +02:00
yann64 dbf0465b0a Comptes actifs/inactifs + stats de section dans le tableau de bord
Utilisateurs actifs/inactifs :
- Migration : colonne is_active (boolean, default true) sur users
- Middleware EnsureUserIsActive : déconnecte les utilisateurs désactivés sur chaque requête
- LoginRequest : bloque la connexion si is_active=false (message explicite)
- Admin : bouton Activer/Désactiver dans la liste et la page d'édition
  Protections : impossible de désactiver son propre compte ou le dernier admin actif
- Badge « Inactif » + opacité réduite sur la ligne dans la liste admin
- Sélection de membres (sources) : filtre is_active=true

Sources liées aux sections :
- Migration : colonne section_id nullable FK sur sources
- Source::section() BelongsTo + Section::sources() HasMany
- Formulaire sources/_form : sélecteur de section (sections de l'utilisateur ou toutes pour admin)
- SourceController : passe les sections disponibles aux vues create/edit

Tableau de bord enrichi (DashboardController) :
- Membres et responsables : stats par section (sources par statut, total relevés)
  compteurs cliquables → liste filtrée, sources récentes de la section
- Mes sources assignées (tri par urgence) + mes derniers relevés (inchangés)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:50:56 +02:00
yann64 9efb6d6093 docs: réécriture complète du README
Description du projet, stack technique, instructions d'installation Docker,
procédures de mise à jour (manuelle, automatique, rollback), guide de
développement, commandes utiles, procédure de release et aperçu de l'architecture.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:42:58 +02:00
yann64 ba7fe10329 Versioning, déploiement et mise à jour automatique
Gestion des versions :
- Fichier VERSION (1.0.0) comme source de vérité
- config/update.php : URL Gitea, AUTO_UPDATE (false par défaut), rétention des sauvegardes

Artisan commands :
- app:check-update  : interroge l'API Gitea, cache Redis 1h, déclenche app:update si AUTO_UPDATE=true
- app:update        : télécharge l'archive, sauvegarde pg_dump, rsync, composer install, migrate, reload php-fpm
- app:rollback      : liste les sauvegardes et restaure via psql

UpdateService :
- Téléchargement via Http::sink() (streaming, pas de charge mémoire)
- Sauvegarde pg_dump dans storage/app/backups/ avant chaque mise à jour
- Rechargement php-fpm gracieux (kill -USR2 1) sans downtime
- Purge automatique des anciennes sauvegardes (configurable)

Docker (refactor pour volume-mount) :
- Dockerfile : runtime seulement (PHP + extensions + composer + rsync + pg_client)
  Le code n'est plus copié dans l'image → les mises à jour ne nécessitent pas de rebuild
- entrypoint.sh : composer install + key:generate + caches au démarrage du container
- docker-compose.prod.yml : montage du code comme volume (.:/var/www/html)

Scripts de déploiement :
- bin/build-release.sh : rsync + tar.gz + sha256, exclut vendor/node_modules/tests
- install.sh : guide d'installation Docker complète (première mise en service)

Interface admin :
- Bandeau "mise à jour disponible" dans le dashboard admin (version courante + cible)
- Badge version + icône "à jour" en pied de tableau de bord
- Commande à copier-coller pour appliquer depuis le container

Planification :
- routes/console.php : Schedule::command('app:check-update')->daily()
- .env.example : variables GITEA_*, AUTO_UPDATE, UPDATE_BACKUPS_TO_KEEP

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:38:39 +02:00
yann64 c790691200 Étape 10 : interface admin (tableau de bord + gestion utilisateurs)
- DashboardController : stats globales (sources par statut, relevés, utilisateurs, activité mensuelle 6 mois)
- UserController : liste filtrée (nom/email/rôle) + édition de rôle avec protections (auto-demotion, dernier admin)
- Vue admin/dashboard : compteurs par statut cliquables, graphique barres mensuel, sources à valider, relevés récents
- Vue admin/utilisateurs : liste paginée avec sections et sources assignées, page d'édition avec radio-cards
- Dashboard principal enrichi : bloc accès admin, mes sources assignées triées par urgence, mes derniers relevés
- Navigation : ajout Tableau de bord admin et Utilisateurs dans le menu Administration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:21:50 +02:00
yann64 d064f8d28e Étapes 6-9 + types de lieux + picker + filtres
- Étape 6 : formulaire de saisie dynamique des relevés (piloté par source_type_fields, calendriers grégorien/julien/républicain)
- Étape 7 : workflow de statut des sources + notifications mail+DB (SourceAValider, SourceRejetee)
- Étape 8 : recherche fulltext PostgreSQL avec filtres type/lieu/années et CTE récursive pour les subdivisions de lieux
- Étape 9 : export GEDCOM 5.5.1 (GedcomExportService + DateConversionService)
- Types de lieux : CRUD admin (LieuTypeController) avec champ ordre
- Composant lieu-picker : modale Alpine.js avec recherche AJAX + debounce
- Filtres sources : statut, type, lieu (CTE récursive), période annee_debut/annee_fin
- Filtres lieux : type, texte, lieu parent avec descendants (CTE récursive)
- Migration : lieu_id + annee_debut + annee_fin sur sources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 17:17:53 +02:00
yann64 7609d35287 Initial scaffold : Laravel 12 + PostgreSQL + auth + domaine métier (étapes 1-5)
- Laravel 12 sur PHP 8.5, Breeze (Blade/Tailwind/Alpine.js)
- Docker Compose dev (PostgreSQL 18 + Redis) et prod (stack complète + nginx)
- Migrations et models : lieux, sections, dépôts, source_types/fields, sources, relevés
  - Colonne JSONB data sur releves avec colonnes générées indexées (nom, prenom, date_evenement)
  - Index GIN pour la recherche fulltext
- Enums : UserRole, SourceStatus (avec transitions), CalendarType, FieldType
- RoleMiddleware (alias `role`) + helpers isAdmin/isSectionManager sur User
- CRUD Lieux (arbre hiérarchique, calcul nom_long en cascade)
- CRUD admin : Sections (+ gestion membres), Dépôts, Types de sources (+ champs dynamiques, drag & drop)
- CRUD Sources : visibilité filtrée par rôle, assignation membres, workflow de statut

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 16:16:37 +02:00