- Corrige le type de retour de UserController::export() (StreamedResponse)
- Ajoute les classes dark mode manquantes sur le bloc info de la page import
- Génère la documentation complète du projet dans docs/documentation.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Vues admin/utilisateurs : route() utilisait $user sans clé nommée ;
Laravel ne résout pas automatiquement un modèle vers un paramètre
{utilisateur} (nom non-anglais) — remplacé par ['utilisateur' => $user]
dans edit.blade.php, index.blade.php et UserController::store()
- Carte : ajout de position:relative + z-index:0 sur #carte-map pour
créer un contexte d'empilement qui confine les z-indexes internes de
Leaflet (≤800) et laisse le menu (z-index:40) s'afficher par-dessus
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin : CRUD complet utilisateurs (créer, modifier nom/email/mdp/rôle, supprimer)
avec garde-fous (dernier admin, compte propre)
- Recherche : limite configurable par l'admin (défaut 200), bannière d'avertissement
quand la limite est atteinte, plus de pagination (résultats en bloc)
- Lieux : liste non chargée sans filtre actif (performance sur grands volumes)
- Sources : idem pour admin/responsables ; membres voient toujours leurs sources
- Logo 404 prod : +FollowSymLinks dans .htaccess, storage:link dans l'assistant
d'installation, bouton "Recréer le lien" dans Administration → Paramètres
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Export (GET lieux/export/csv) :
- Colonnes : nom, code, type, lieu_parent (nom_long), latitude, longitude, note
- BOM UTF-8, séparateur point-virgule
Import (GET/POST lieux/import) :
- Correspondance par nom de colonne (colonne nom obligatoire)
- Résolution du parent par nom_long exact
- Résolution du type par nom exact
- Détection automatique du séparateur ; ou ,
- nom_long recalculé automatiquement par le modèle
Boutons ↓ CSV, ↑ Importer CSV et + Nouveau lieu dans la liste des lieux.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Le champ de connexion accepte désormais les deux :
- Si la saisie contient un @, Auth::attempt() cherche par email
- Sinon, cherche par name
Champ renommé login dans le formulaire et la LoginRequest.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Leaflet positionne ses couches internes avec z-index jusqu'à 800.
La <nav> sans stacking context propre laissait ses dropdowns (z-50)
passer derrière. Ajout de relative z-40 sur <nav> : crée un stacking
context, les dropdowns (z-50 à l'intérieur) s'affichent par-dessus la carte.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Le CDN unpkg.com échoue si le serveur n'a pas accès à Internet.
- npm install leaflet
- resources/js/carte.js : point d'entrée qui importe Leaflet + expose window.LeafletMap
- vite.config.js : ajoute carte.js aux inputs compilés
- carte/index.blade.php : @vite au lieu du CDN, utilise window.LeafletMap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ExportController::sourceCsv() : génère un CSV avec BOM UTF-8 (compatible Excel)
séparateur point-virgule, en-têtes = labels des champs, valeurs formatées
(dates avec calendrier si non grégorien, lieux = nom_long, booléens Oui/Non)
- Route GET export/source/{source}/csv → export.source.csv
- Boutons ↓ CSV et ↓ GEDCOM dans la section relevés de la fiche source
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- FieldType::Place = 'place' dans l'enum
- _field.blade.php : composant lieu-picker réutilisé pour la saisie
- Validation : integer + exists:lieux,id dans Store/UpdateReleveRequest
- buildData() : stocke {id, nom_long} dans le JSONB (évite les requêtes à l'affichage)
- releves/show.blade.php : affiche nom_long pour les champs de type place
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Les deux inputs [valeur] (date et texte républicain) avaient le même name.
x-show ne fait que display:none — les deux étaient soumis, PHP prenait le
dernier (républicain vide), ce qui échouait la validation 'required'.
Correction : :disabled="..." sur chaque input pour qu'il ne soit pas soumis.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Le x-data était scopé au bouton seul, rien ne réagissait à open.
- x-data remonté sur le <li> (scope partagé avec le formulaire)
- Formulaire inline avec x-show="open" pour éditer nom/label/type/required/options
- Bouton bascule Modifier ↔ Annuler
- updateField() gère désormais options_raw comme storeField()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
- 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>
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>
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>
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>
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>
- 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>
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>
- 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>
- 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>
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>
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>
- 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>