Ajout de la route GET /api/calendar/force-oauth2 pour forcer
le changement du type d'authentification vers OAuth2 dans la BDD.
Cette route permet de contourner un problème où le bouton
"Enregistrer" ne sauvegarde pas correctement google_auth_type.
Ajout d'une troisième méthode d'authentification pour Google Calendar :
- OAuth 2.0 (existant)
- Service Account (existant)
- API Key (nouveau)
Modifications :
- Interface d'administration avec sélection API Key
- Champs pour configurer la clé API et l'ID du calendrier
- Backend mis à jour pour gérer l'authentification par API Key
- Routes calendar adaptées pour supporter le nouveau type
- Affichage du statut de connexion mis à jour
L'utilisateur peut maintenant :
1. Sélectionner "API externe" dans les paramètres Google Calendar
2. Entrer sa clé API Google Calendar
3. Spécifier l'ID du calendrier (ou "primary")
4. Synchroniser directement avec Google Calendar
Ajout de deux méthodes d'authentification au choix pour Google Calendar :
1. **OAuth 2.0** (méthode existante améliorée) :
- ✅ Prompt de sélection de compte Google ('select_account consent')
- ✅ Gestion dynamique du redirect_uri avec APP_URL
- ✅ Idéal pour accès au calendrier personnel avec consentement
2. **Service Account** (nouvelle méthode) :
- ✅ Authentification via clé JSON sans interaction utilisateur
- ✅ Parfait pour calendriers partagés en entreprise
- ✅ Synchronisation automatique en arrière-plan
- ✅ Configuration de l'email du calendrier à synchroniser
## Backend (routes/calendar.routes.js) :
- Ajout des constantes AUTH_TYPES (oauth2, service_account)
- Fonction getAuthType() pour récupérer la méthode configurée
- Fonction getServiceAccountClient() pour Service Account
- Fonction getCalendarClient() unifiée qui choisit la bonne méthode
- Route /auth-status mise à jour pour retourner le type d'auth
- Route /sync adaptée pour supporter les deux méthodes
- Support du calendrier email personnalisé pour Service Account
## Frontend (src/pages/Index.tsx) :
- Menu déroulant pour choisir entre OAuth2 et Service Account
- Interface conditionnelle selon la méthode choisie
- Champ textarea pour la clé JSON du Service Account
- Champ email pour spécifier le calendrier à synchroniser
- Affichage du type d'authentification dans le statut
- Amélioration de l'UI avec descriptions claires
## Documentation :
- OAUTH_SETUP.md : Guide complet mis à jour avec les deux méthodes
- Section dédiée au choix de la méthode
- Guide pas à pas pour Service Account
- Dépannage pour les deux méthodes
- README_GOOGLE_CALENDAR.md : Guide de démarrage rapide (nouveau)
- Comparaison des deux méthodes
- Configuration rapide pour chaque méthode
- Liens vers la documentation complète
Cette implémentation offre une flexibilité maximale pour s'adapter
à différents cas d'usage : personnel (OAuth2) ou professionnel (Service Account).
Corrections apportées :
1. **redirect_uri_mismatch** :
- Ajout de la variable APP_URL dans .env.example avec documentation
- Amélioration de la fonction getOAuth2Client pour accepter une URI personnalisée
- Gestion plus flexible du redirect_uri (APP_URL ou localhost par défaut)
2. **Choix du compte Google** :
- Modification du prompt OAuth : 'consent' → 'select_account consent'
- Force maintenant l'affichage du sélecteur de compte Google
3. **Interface utilisateur** :
- Ajout d'un encadré d'avertissement visible avec l'URL de redirection exacte
- Instructions claires pour la configuration dans Google Cloud Console
- Indication pour configurer APP_URL si nécessaire
4. **Documentation** :
- Création du fichier OAUTH_SETUP.md avec guide complet
- Checklist de vérification pour le débogage
- Exemples de configuration pour local et production
Ces modifications permettent de résoudre l'erreur 400 redirect_uri_mismatch
et d'offrir le choix du compte Google lors de la connexion.
Corrections critiques:
1. Ajout de la route PUT /api/settings manquante
- Permet la mise à jour de plusieurs paramètres en une fois
- Utilisé par le frontend pour sauvegarder la configuration
- Erreur 404 résolue
2. Configuration trust proxy dans Express
- app.set('trust proxy', true)
- Nécessaire car l'application est derrière nginx/proxy
- Résout l'erreur express-rate-limit avec X-Forwarded-For
- Permet d'obtenir la vraie IP du client
Routes settings maintenant complètes:
- GET /api/settings - Récupérer tous les paramètres
- PUT /api/settings - Mettre à jour plusieurs paramètres (NOUVEAU)
- GET /api/settings/:key - Récupérer un paramètre
- PUT /api/settings/:key - Mettre à jour un paramètre
- DELETE /api/settings/:key - Supprimer un paramètre
Problème majeur résolu:
- L'éditeur de notes réinitialisait le contenu à chaque modification
- Causé par dangerouslySetInnerHTML qui forçait React à synchroniser
- Résultat: impossible d'éditer les notes correctement
Solution:
- Suppression de dangerouslySetInnerHTML du RichTextEditor
- Conservation du useEffect avec deps vides pour initialisation unique
- Utilisation du key prop pour forcer remount lors du changement de note
- Éditeur maintenant complètement "uncontrolled"
Migration complète Google Calendar vers OAuth 2.0:
- Remplacement de l'API Key simple par OAuth 2.0 (Client ID + Secret)
- Nouvelle table google_oauth_tokens pour stocker les tokens
- Routes OAuth:
* GET /api/calendar/auth-url - Génère l'URL d'authentification
* GET /api/calendar/oauth-callback - Callback OAuth avec échange de code
* GET /api/calendar/auth-status - Vérifier le statut de connexion
* POST /api/calendar/disconnect - Déconnecter Google
- Gestion automatique du rafraîchissement des tokens expirés
- Interface utilisateur mise à jour:
* Champs Client ID et Client Secret
* Indicateur de statut de connexion (connecté/non connecté)
* Bouton "Se connecter avec Google" ouvrant popup OAuth
* Bouton "Déconnecter"
* URI de redirection affichée pour configuration Google Cloud Console
- Synchronisation maintenant avec calendrier principal de l'utilisateur
- Accès complet aux données privées du calendrier
Architecture:
- CalendarService.ts: Nouvelles méthodes getAuthUrl(), getAuthStatus(), disconnect()
- Settings: Ajout de google_client_id et google_client_secret
- Popup OAuth avec communication window.postMessage
- Gestion d'erreur avec re-authentification automatique si token expiré
Corrections:
- Correction de l'import des middlewares dans openrouter.routes.js
- Utilisation de authenticateToken au lieu de requireAuth
- Fix du bug qui empêchait le serveur de démarrer
Le serveur crashait avec l'erreur:
Error: Route.get() requires a callback function but got a [object Undefined]
Résolu en utilisant le bon nom de middleware.
Ajouts majeurs:
- Système de tags complet pour les notes
* Table note_tags en base de données avec indexes
* API REST pour CRUD des tags (GET/POST/DELETE)
* UI avec onglet Tags dans l'éditeur de notes
* Badges cliquables avec icônes et suppression au survol
* Modal pour ajouter des tags
- Liste automatique des modèles OpenRouter
* Nouvelle route API /api/openrouter/models
* Cache des modèles avec rafraîchissement automatique (1h)
* Dropdown dans l'admin avec tous les modèles disponibles
* Bouton "Actualiser" pour forcer le refresh
* Affichage du nom et description de chaque modèle
* Fallback sur input manuel si pas de clé API
Améliorations UI:
- Ajout de dates de création et modification dans les notes
- Affichage des dates dans les cartes et l'éditeur
- Format français pour toutes les dates
- Onglets passés de 4 à 5 colonnes pour inclure Tags
- Animation de chargement sur le bouton refresh des modèles
Architecture:
- Nouveau service TagsService.ts pour la gestion des tags
- Nouveau service OpenRouterService.ts pour l'API OpenRouter
- Nouvelles routes openrouter.routes.js
- Support Select component pour les dropdowns
- Modals InputModal utilisés pour les tags
Modaux :
- Création ConfirmModal pour confirmations avec variants (default/destructive)
- Création InputModal pour saisie de texte/URL/mot de passe
- Création AddUserModal pour création d'utilisateur avec admin checkbox
- Remplacement de tous les prompt() et confirm() par des modaux modernes
- Modaux pour : suppression note, ajout todo, ajout RSS, ajout utilisateur, suppression utilisateur, changement mot de passe, ajout todo dans note
Fix RSS :
- Ajout route POST /api/rss/refresh (alias de /api/rss/fetch)
- Fix uploadImage retour avec result.image || result
UX améliorée :
- Plus de popups navigateur natifs
- Interface cohérente et moderne
- Validation dans les modaux
- Support touche Entrée dans les InputModals
- Auto-focus sur le champ de saisie
Images multiples :
- Ajout table note_images dans la base de données
- Routes POST/GET/DELETE /api/notes/:id/images
- Dossier uploads/images séparé pour les images
- Support de plusieurs images par note
Google Calendar :
- Ajout table calendar_events
- Routes /api/calendar pour sync et récupération des événements
- Box Rendez-vous dans l'interface avec affichage des événements à venir
- Configuration Google Calendar dans l'admin (API key et Calendar ID)
- Synchronisation manuelle avec Google Calendar API
- Installation package googleapis
Corrections :
- Fix RichTextEditor: ajout dir="ltr" pour empêcher l'écriture RTL
- Fix Image type conflict (lucide-react vs Note interface)
- Ajout original_name à l'interface Image pour compatibilité
Interface :
- Box Rendez-vous empilée avec Todos et RSS dans la colonne droite
- Nouvel onglet Google Calendar dans l'administration
- Bouton "Synchroniser" pour rafraîchir les événements
Cette mise à jour améliore l'interface utilisateur des tâches et des flux RSS
avec une meilleure organisation et de nouvelles fonctionnalités.
Changements principaux:
1. **Layout Todos et RSS côte à côte**
- Les deux boxes sont maintenant affichées côte à côte
- Meilleure utilisation de l'espace disponible
- Layout en grid responsive
2. **Système d'onglets pour les Todos**
- Onglet "Actives" : affiche uniquement les tâches non complétées
- Onglet "Complétées" : affiche les tâches terminées avec style barré
- Séparation claire entre tâches en cours et terminées
- Possibilité de re-activer une tâche complétée en cliquant dessus
3. **Endpoint PATCH /api/todos/:id/toggle ajouté**
- Nouvelle route backend pour basculer l'état d'une tâche
- Résout l'erreur 404 précédente
- Logging des actions pour suivi
4. **Optimisations visuelles**
- Tailles de texte réduites (text-xs) pour plus de contenu visible
- Hauteurs de boutons optimisées
- Espacements améliorés
- Animations et transitions fluides
Fichiers modifiés:
- routes/todos.routes.js : ajout de la route toggle
- src/pages/Index.tsx : refonte de la sidebar droite avec onglets
Cette version améliore significativement l'expérience utilisateur pour
la gestion des tâches avec une séparation claire entre tâches actives
et complétées.
1. Titre 'À faire' au lieu de 'Quick Tasks'
- Changé public/index.html ligne 126
- Meilleure localisation française
2. Affichage source RSS au lieu du modèle IA
- Ajout colonne feed_title à rss_summaries (migration auto)
- Backend stocke feed_title lors de la génération
- GET /api/rss/summaries retourne feed_title
- Frontend affiche 📰 Source + 📅 Date au lieu du modèle
- Plus pertinent pour l'utilisateur
3. Tri automatique des todos : actives en premier
- renderTodos() trie : actives avant complétées
- Si même statut : tri par ID décroissant (récentes en premier)
- Sort: a.completed ? 1 : -1
4. Système de notifications internes
- Remplacé TOUS les alert() par showNotification()
- Types : success, error, warning, info
- Animations : slide-in/slide-out depuis la droite
- Auto-fermeture après 4 secondes
- Bouton de fermeture manuelle
- Position : top-right, z-index 300
- Icônes SVG selon le type
- Couleurs : vert (success), rouge (error), jaune (warning), bleu (info)
Frontend - Notifications:
- showNotification(message, type, duration)
- closeNotification(notification)
- Container fixe en haut à droite
- Empilage vertical des notifications
- Escape HTML automatique
CSS - Nouveaux styles:
- .notifications-container (fixed, top-right)
- .notification + variations par type
- Animations slideInRight / slideOutRight
- Border-left colorée selon le type
- Responsive et accessible
Impact utilisateur:
✓ Plus de popups système alert() invasives
✓ Notifications élégantes et non-bloquantes
✓ Feedback visuel clair avec icônes et couleurs
✓ Source RSS affichée au lieu du modèle IA
✓ Todos actives toujours en haut
✓ Interface 100% en français
Files:
- public/index.html: Titre + container notifications
- public/css/skeleton.css: Styles notifications
- public/js/complete-app.js: showNotification() + remplacement 40+ alert()
- config/database.js: Migration feed_title
- routes/rss.routes.js: Stockage et retour feed_title
Résumés RSS par article (100 mots max):
- Modifié route POST /api/rss/summarize pour générer un résumé PAR article
- Chaque résumé limité à 100 mots (max_tokens: 200)
- Format: **Titre** + Résumé + 🔗 [Lire l'article](lien)
- Résumés générés en parallèle pour meilleure performance
- Supprimé requireAdmin pour accès à tous utilisateurs authentifiés
- Timeout 30s par article au lieu de 60s global
Frontend - Affichage résumés:
- renderRssSummaries() : Détection auto ancien/nouveau format
- formatSummary() : Support liens markdown [texte](url)
- summarizeRss() : Gère tableau de résumés au lieu d'un seul
- Styles CSS pour .rss-link (hover avec underline)
- Nouveau style .rss-summary-article pour résumés individuels
Optimisation pour écran 1920x1080:
- max-width: 1400px → 1800px (utilise mieux l'espace horizontal)
- todo-box-width: 340px → 420px (+80px de largeur)
- Boxes TODO et RSS élargies de 23%
- Grille: ~960px notes + 420px todo + 420px rss = 1800px
- Layout optimisé pour grand écran
CSS - Nouveaux styles:
- .rss-link : liens cliquables avec hover effect
- .rss-summary-article : carte compacte pour résumé individuel
- Hover effects sur liens et cartes
- Responsive maintenu pour petits écrans
Impact utilisateur:
✓ Un résumé par article avec lien direct
✓ Plus concis (100 mots max vs résumé global)
✓ Interface plus large et spacieuse sur 1920x1080
✓ Boxes TODO et RSS 23% plus larges
✓ Meilleure lisibilité des contenus
Files:
- routes/rss.routes.js: Nouveau système de résumés par article
- public/js/complete-app.js: Rendu et gestion résumés
- public/css/variables.css: Dimensions optimisées 1920x1080
- public/css/layout.css: Styles liens + résumés individuels
Problèmes résolus:
✅ Flux RSS ne s'affichaient pas → LEFT JOIN + COALESCE
✅ Pas de mise à jour automatique → Scheduler toutes les 5min
✅ Application lente → Cache serveur + client
Scheduler RSS (services/rss-scheduler.js):
- Mise à jour automatique des flux toutes les 5 minutes
- Première exécution 5 secondes après démarrage
- Gestion parallèle de tous les flux activés
- Logs détaillés pour debugging
- Protection contre les exécutions multiples simultanées
- Limite de 20 articles par flux pour performance
Routes RSS optimisées:
- Cache serveur 30 secondes pour /api/rss/articles
- Invalidation cache après fetch manuel
- LEFT JOIN au lieu de INNER JOIN (flux sans articles)
- COALESCE pour titre fallback
- Logs améliorés avec compteurs
Frontend vanilla JS:
- Auto-refresh RSS toutes les 30 secondes
- Cache settings client 1 minute
- Synchronisation avec scheduler serveur
- console.debug au lieu de console.error pour auto-refresh
Frontend React:
- Auto-refresh RSS toutes les 30 secondes
- loadRssData() séparée pour refresh indépendant
- useEffect cleanup proper (clearInterval)
- État lastUpdate pour tracking
Server.js:
- Démarrage scheduler au startup
- Log confirmation démarrage
Performances:
- Moins de requêtes DB grâce au cache
- Refresh automatique sans action utilisateur
- Articles toujours à jour (max 30s de délai)
- Support de beaucoup de flux RSS sans ralentissement
Backend:
- Récupération des vrais modèles depuis l'API OpenRouter
- Table rss_summaries pour stocker les résumés générés
- Limitation à 5 articles RSS au lieu de 10
- Route GET /api/rss/summaries pour récupérer les résumés
- Sauvegarde automatique des résumés en base de données
Frontend:
- Affichage conditionnel: résumés si activé, sinon articles
- Fonction renderRssSummaries() avec conversion Markdown→HTML
- Formatage du résumé (titres, listes, gras, italique)
- CSS complet pour .rss-summary avec typography
- Bouton résumer: crée note ou recharge bloc selon config
Comportement:
- Si rss_summary_enabled=1: affiche les 5 derniers résumés
- Sinon: affiche les 5 derniers articles
- Résumés formatés avec Markdown dans le bloc RSS
## Base de données:
- Table settings (key-value pour paramètres globaux)
- Table rss_feeds (url, title, description, enabled, last_fetched_at)
- Table rss_articles (feed_id, title, link, description, pub_date, content)
- Index optimisés pour performance
## Routes Settings (/api/settings):
- GET /api/settings - Récupérer tous les paramètres
- GET /api/settings/:key - Récupérer un paramètre
- PUT /api/settings/:key - Mettre à jour un paramètre
- DELETE /api/settings/:key - Supprimer un paramètre
- Middleware requireAdmin sur toutes les routes
## Routes RSS (/api/rss):
- GET /api/rss/feeds - Liste des flux RSS (admin)
- POST /api/rss/feeds - Ajouter flux RSS avec parsing validation (admin)
- PUT /api/rss/feeds/:id - Activer/désactiver flux (admin)
- DELETE /api/rss/feeds/:id - Supprimer flux (admin)
- POST /api/rss/fetch - Récupérer articles de tous flux actifs (admin)
- GET /api/rss/articles - Récupérer 10 derniers articles (tous users)
- POST /api/rss/summarize - Générer résumé OpenRouter (admin)
- GET /api/rss/models - Liste modèles OpenRouter (admin)
## Intégration OpenRouter:
- Appel API avec clé, modèle et prompt configurables
- Résumé intelligent des 10 derniers articles
- Prompt par défaut optimisé pour résumés d'actualités
- Support GPT-4, Claude 3, Gemini, Llama 3, Mistral, etc.
- Gestion erreurs et timeout
## Parser RSS:
- rss-parser installé pour parsing flux
- Gestion articles avec contenu, description, date
- Détection doublons par URL
- Update automatique infos flux
## Frontend HTML:
- Modal admin avec système à onglets (Users/RSS/OpenRouter)
- Modal changement mot de passe sans prompt navigateur
- Box RSS dans page principale affichage 10 derniers articles
- Bouton résumé IA dans header box RSS
- Inputs pour gestion flux RSS
- Configuration OpenRouter (API key, modèle, prompt, activation)
- Sélecteur modèles avec recherche
Prochaine étape: CSS + JavaScript pour fonctionnalités
## Corrections UX:
- Fix coins arrondis en bas des notes étendues (overflow: hidden)
- Remplacement prompt() par input inline pour ajout de tâches
- Bouton "Ajouter" avec validation au clic ou touche Entrée
- Expérience utilisateur fluide sans popups intrusifs
## Système de fichiers complet:
### Backend:
- Création table note_files (id, note_id, filename, original_name, file_size, mime_type, created_at)
- POST /api/notes/:id/files - Upload fichier (multer, 10MB max)
- GET /api/notes/:id/files - Liste fichiers d'une note
- GET /api/notes/files/:fileId/download - Téléchargement sécurisé
- DELETE /api/notes/files/:fileId - Suppression fichier
- Stockage dans public/uploads/files/
- Auto-création dossier si nécessaire
### Frontend:
- Bouton "Ajouter un fichier" dans footer des notes
- Input hidden fileInput pour sélection
- Affichage liste fichiers avec icône, nom, taille
- Boutons télécharger/supprimer par fichier
- Fonction formatFileSize() pour affichage lisible
- Event delegation pour tous les boutons fichiers
- Confirmation avant suppression
### Intégration:
- GET /api/notes charge maintenant files[] et files_count
- renderInlineFiles() génère HTML des fichiers
- downloadFile() ouvre download dans nouvel onglet
- deleteFile() avec confirmation dialog
- Reload automatique après upload/delete
- Conservation état étendu après opérations
### CSS moderne:
- .note-file-item avec hover effect
- .note-file-icon, .note-file-info, .note-file-actions
- Buttons download/delete avec transitions
- Design cohérent avec reste de l'app
- Truncate nom fichier avec ellipsis
Tous types de fichiers acceptés (PDF, DOC, ZIP, etc.)
- Migration auto colonne archived (BOOLEAN DEFAULT 0)
- Route GET /api/notes?archived=true/false pour filtrer
- Route PUT /api/notes/:id/archive pour archiver/désarchiver
- Chargement des todos avec chaque note (todos[], todos_count, todos_completed)
- Support filtrage par statut archivé
- Logs archivage/désarchivage
- Remplacement de COUNT(DISTINCT) par une sous-requête dans SQLite
- Ajout de vérification Array.isArray côté client
- Gestion d'erreur améliorée avec fallback sur tableau vide
- Correction du bug 'filtered.forEach is not a function'
- L'API retourne toujours un tableau, même en cas d'erreur