Add logo and rename

This commit is contained in:
2025-11-12 17:16:13 +01:00
parent 584a4a0acd
commit f903e28728
49 changed files with 628 additions and 192 deletions

View File

@ -212,6 +212,12 @@ func (h *Handler) handleDailyCalendar(w http.ResponseWriter, r *http.Request, ye
return
}
// Si ce n'est pas une requête HTMX, rediriger vers la page principale
if r.Header.Get("HX-Request") == "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// Parser année et mois
year, err := strconv.Atoi(yearStr)
if err != nil || year < 1900 || year > 2100 {
@ -353,6 +359,12 @@ func (h *Handler) handleDailyRecent(w http.ResponseWriter, r *http.Request) {
return
}
// Si ce n'est pas une requête HTMX, rediriger vers la page principale
if r.Header.Get("HX-Request") == "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// Chercher les daily notes des 14 derniers jours (au cas où certaines manquent)
recentNotes := make([]*DailyNoteInfo, 0, 7)

View File

@ -87,38 +87,45 @@ func (h *Handler) handleFavorites(w http.ResponseWriter, r *http.Request) {
// handleGetFavorites retourne la liste des favoris (HTML)
func (h *Handler) handleGetFavorites(w http.ResponseWriter, r *http.Request) {
// Pas de redirection ici car cet endpoint est utilisé par HTMX ET par fetch()
// depuis le JavaScript pour mettre à jour la liste après ajout/suppression
h.renderFavoritesList(w)
}
// renderFavoritesList rend le template des favoris (méthode interne)
func (h *Handler) renderFavoritesList(w http.ResponseWriter) {
favorites, err := h.loadFavorites()
if err != nil {
h.logger.Printf("Erreur chargement favoris: %v", err)
// En cas d'erreur, retourner une liste vide plutôt qu'une erreur 500
favorites = &FavoritesData{Items: []Favorite{}}
}
// Enrichir avec les informations des fichiers
enrichedFavorites := []map[string]interface{}{}
for _, fav := range favorites.Items {
absPath := filepath.Join(h.notesDir, fav.Path)
// Vérifier si le fichier/dossier existe toujours
if _, err := os.Stat(absPath); os.IsNotExist(err) {
continue // Skip les favoris qui n'existent plus
}
item := map[string]interface{}{
"Path": fav.Path,
"IsDir": fav.IsDir,
"Title": fav.Title,
"Icon": getIcon(fav.IsDir, fav.Path),
}
enrichedFavorites = append(enrichedFavorites, item)
}
data := map[string]interface{}{
"Favorites": enrichedFavorites,
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := h.templates.ExecuteTemplate(w, "favorites.html", data); err != nil {
h.logger.Printf("Erreur template favoris: %v", err)
@ -192,24 +199,34 @@ func (h *Handler) handleAddFavorite(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Erreur de sauvegarde", http.StatusInternalServerError)
return
}
// Retourner la liste mise à jour
h.handleGetFavorites(w, r)
h.renderFavoritesList(w)
}
// handleRemoveFavorite retire un élément des favoris
func (h *Handler) handleRemoveFavorite(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
// Pour DELETE, il faut lire le body manuellement
body, _ := io.ReadAll(r.Body)
r.Body.Close()
values, _ := url.ParseQuery(string(body))
r.Form = values
// Pour DELETE, il faut toujours lire le body manuellement
// car ParseForm() ne lit pas le body pour les méthodes DELETE
body, err := io.ReadAll(r.Body)
if err != nil {
h.logger.Printf("Erreur lecture body: %v", err)
http.Error(w, "Erreur lecture requête", http.StatusBadRequest)
return
}
path := r.FormValue("path")
r.Body.Close()
values, err := url.ParseQuery(string(body))
if err != nil {
h.logger.Printf("Erreur parsing query: %v", err)
http.Error(w, "Erreur parsing requête", http.StatusBadRequest)
return
}
path := values.Get("path")
if path == "" {
h.logger.Printf("Chemin requis manquant dans la requête")
http.Error(w, "Chemin requis", http.StatusBadRequest)
return
}
@ -243,15 +260,15 @@ func (h *Handler) handleRemoveFavorite(w http.ResponseWriter, r *http.Request) {
}
favorites.Items = newItems
if err := h.saveFavorites(favorites); err != nil {
h.logger.Printf("Erreur sauvegarde favoris: %v", err)
http.Error(w, "Erreur de sauvegarde", http.StatusInternalServerError)
return
}
// Retourner la liste mise à jour
h.handleGetFavorites(w, r)
h.renderFavoritesList(w)
}
// handleReorderFavorites réorganise l'ordre des favoris

View File

@ -16,7 +16,7 @@ import (
yaml "gopkg.in/yaml.v3"
"github.com/mathieu/project-notes/internal/indexer"
"github.com/mathieu/personotes/internal/indexer"
)
// TreeNode représente un nœud dans l'arborescence des fichiers
@ -235,6 +235,12 @@ func (h *Handler) handleFileTree(w http.ResponseWriter, r *http.Request) {
return
}
// Si ce n'est pas une requête HTMX, rediriger vers la page principale
if r.Header.Get("HX-Request") == "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
tree, err := h.buildFileTree()
if err != nil {
h.logger.Printf("erreur lors de la construction de l arborescence: %v", err)
@ -261,18 +267,26 @@ func (h *Handler) handleHome(w http.ResponseWriter, r *http.Request) {
return
}
// Si ce n'est pas une requête HTMX (ex: accès direct via URL), rediriger vers la page principale
if r.Header.Get("HX-Request") == "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// Générer le contenu Markdown avec la liste de toutes les notes
content := h.generateHomeMarkdown()
// Utiliser le template editor.html pour afficher la page d'accueil
data := struct {
Filename string
Content string
IsHome bool
Filename string
Content string
IsHome bool
Backlinks []BacklinkInfo
}{
Filename: "🏠 Accueil - Index",
Content: content,
IsHome: true,
Filename: "🏠 Accueil - Index",
Content: content,
IsHome: true,
Backlinks: nil, // Pas de backlinks pour la page d'accueil
}
err := h.templates.ExecuteTemplate(w, "editor.html", data)
@ -577,13 +591,15 @@ func (h *Handler) createAndRenderNote(w http.ResponseWriter, r *http.Request, fi
initialContent := "---\n" + string(fmBytes) + "---\n\n# " + newFM.Title + "\n\nCommencez à écrire votre note ici..."
data := struct {
Filename string
Content string
IsHome bool
Filename string
Content string
IsHome bool
Backlinks []BacklinkInfo
}{
Filename: filename,
Content: initialContent,
IsHome: false,
Filename: filename,
Content: initialContent,
IsHome: false,
Backlinks: nil, // Pas de backlinks pour une nouvelle note
}
err = h.templates.ExecuteTemplate(w, "editor.html", data)
@ -599,6 +615,11 @@ func (h *Handler) handleSearch(w http.ResponseWriter, r *http.Request) {
return
}
// Pas de redirection ici car cet endpoint est utilisé par:
// 1. La sidebar de recherche (HTMX)
// 2. La modale de recherche Ctrl+K (fetch)
// 3. Le link inserter pour créer des backlinks (fetch)
query := strings.TrimSpace(r.URL.Query().Get("query"))
if query == "" {
query = strings.TrimSpace(r.URL.Query().Get("tag"))
@ -673,6 +694,13 @@ func (h *Handler) handleDeleteNote(w http.ResponseWriter, r *http.Request, filen
}
func (h *Handler) handleGetNote(w http.ResponseWriter, r *http.Request, filename string) {
// Si ce n'est pas une requête HTMX (ex: refresh navigateur), rediriger vers la page principale
// Cela évite d'afficher un fragment HTML sans CSS lors d'un Ctrl+F5
if r.Header.Get("HX-Request") == "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
fullPath := filepath.Join(h.notesDir, filename)
content, err := os.ReadFile(fullPath)
if err != nil {
@ -800,8 +828,12 @@ func (h *Handler) handlePostNote(w http.ResponseWriter, r *http.Request, filenam
}
}()
// Repondre a htmx pour vider l'editeur et rafraichir l'arborescence
h.renderFileTreeOOB(w)
// Pour les notes existantes, ne pas recharger le file-tree (évite de fermer les dossiers ouverts)
// Le file-tree sera rechargé uniquement lors de la création de nouveaux fichiers/dossiers
if isNewFile {
// Nouvelle note : mettre à jour le file-tree pour l'afficher
h.renderFileTreeOOB(w)
}
// Répondre avec les statuts de sauvegarde OOB
nowStr := time.Now().Format("15:04:05")

View File

@ -11,7 +11,7 @@ import (
"strings"
"testing"
"github.com/mathieu/project-notes/internal/indexer"
"github.com/mathieu/personotes/internal/indexer"
)
func newTestHandler(t *testing.T, notesDir string) *Handler {

View File

@ -12,7 +12,7 @@ import (
yaml "gopkg.in/yaml.v3"
"github.com/mathieu/project-notes/internal/indexer"
"github.com/mathieu/personotes/internal/indexer"
)
// REST API Structures

View File

@ -11,7 +11,7 @@ import (
"github.com/fsnotify/fsnotify"
"github.com/mathieu/project-notes/internal/indexer"
"github.com/mathieu/personotes/internal/indexer"
)
// Watcher observe les modifications dans le repertoire des notes et relance l indexation au besoin.