Add logo and rename
This commit is contained in:
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
Reference in New Issue
Block a user