Des tonnes de modifications notamment VIM / Couleurs / typos
This commit is contained in:
305
internal/api/favorites.go
Normal file
305
internal/api/favorites.go
Normal file
@ -0,0 +1,305 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Favorite représente un élément favori (note ou dossier)
|
||||
type Favorite struct {
|
||||
Path string `json:"path"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Title string `json:"title"`
|
||||
AddedAt time.Time `json:"added_at"`
|
||||
Order int `json:"order"`
|
||||
}
|
||||
|
||||
// FavoritesData contient la liste des favoris
|
||||
type FavoritesData struct {
|
||||
Items []Favorite `json:"items"`
|
||||
}
|
||||
|
||||
// getFavoritesFilePath retourne le chemin du fichier de favoris
|
||||
func (h *Handler) getFavoritesFilePath() string {
|
||||
return filepath.Join(h.notesDir, ".favorites.json")
|
||||
}
|
||||
|
||||
// loadFavorites charge les favoris depuis le fichier JSON
|
||||
func (h *Handler) loadFavorites() (*FavoritesData, error) {
|
||||
path := h.getFavoritesFilePath()
|
||||
|
||||
// Si le fichier n'existe pas, retourner une liste vide
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return &FavoritesData{Items: []Favorite{}}, nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var favorites FavoritesData
|
||||
if err := json.Unmarshal(data, &favorites); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Trier par ordre
|
||||
sort.Slice(favorites.Items, func(i, j int) bool {
|
||||
return favorites.Items[i].Order < favorites.Items[j].Order
|
||||
})
|
||||
|
||||
return &favorites, nil
|
||||
}
|
||||
|
||||
// saveFavorites sauvegarde les favoris dans le fichier JSON
|
||||
func (h *Handler) saveFavorites(favorites *FavoritesData) error {
|
||||
path := h.getFavoritesFilePath()
|
||||
|
||||
data, err := json.MarshalIndent(favorites, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(path, data, 0644)
|
||||
}
|
||||
|
||||
// handleFavorites route les requêtes /api/favorites/*
|
||||
func (h *Handler) handleFavorites(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
h.handleGetFavorites(w, r)
|
||||
case http.MethodPost:
|
||||
h.handleAddFavorite(w, r)
|
||||
case http.MethodDelete:
|
||||
h.handleRemoveFavorite(w, r)
|
||||
case http.MethodPut:
|
||||
h.handleReorderFavorites(w, r)
|
||||
default:
|
||||
http.Error(w, "Méthode non autorisée", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// handleGetFavorites retourne la liste des favoris (HTML)
|
||||
func (h *Handler) handleGetFavorites(w http.ResponseWriter, r *http.Request) {
|
||||
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)
|
||||
http.Error(w, "Erreur de rendu", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// handleAddFavorite ajoute un élément aux favoris
|
||||
func (h *Handler) handleAddFavorite(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
h.logger.Printf("Erreur ParseForm: %v", err)
|
||||
http.Error(w, "Formulaire invalide", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
path := r.FormValue("path")
|
||||
isDir := r.FormValue("is_dir") == "true"
|
||||
title := r.FormValue("title")
|
||||
|
||||
h.logger.Printf("handleAddFavorite: path='%s', is_dir='%s', title='%s'", path, r.FormValue("is_dir"), title)
|
||||
|
||||
if path == "" {
|
||||
h.logger.Printf("Erreur: chemin vide")
|
||||
http.Error(w, "Chemin requis", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Valider que le fichier/dossier existe
|
||||
absPath := filepath.Join(h.notesDir, path)
|
||||
if _, err := os.Stat(absPath); os.IsNotExist(err) {
|
||||
http.Error(w, "Fichier/dossier introuvable", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Si pas de titre, utiliser le nom du fichier
|
||||
if title == "" {
|
||||
title = filepath.Base(path)
|
||||
if !isDir && filepath.Ext(title) == ".md" {
|
||||
title = title[:len(title)-3]
|
||||
}
|
||||
}
|
||||
|
||||
favorites, err := h.loadFavorites()
|
||||
if err != nil {
|
||||
h.logger.Printf("Erreur chargement favoris: %v", err)
|
||||
http.Error(w, "Erreur de chargement", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Vérifier si déjà en favoris
|
||||
for _, fav := range favorites.Items {
|
||||
if fav.Path == path {
|
||||
http.Error(w, "Déjà en favoris", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Ajouter le nouveau favori
|
||||
newFavorite := Favorite{
|
||||
Path: path,
|
||||
IsDir: isDir,
|
||||
Title: title,
|
||||
AddedAt: time.Now(),
|
||||
Order: len(favorites.Items),
|
||||
}
|
||||
|
||||
favorites.Items = append(favorites.Items, newFavorite)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
path := r.FormValue("path")
|
||||
|
||||
if path == "" {
|
||||
http.Error(w, "Chemin requis", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
favorites, err := h.loadFavorites()
|
||||
if err != nil {
|
||||
h.logger.Printf("Erreur chargement favoris: %v", err)
|
||||
http.Error(w, "Erreur de chargement", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Retirer le favori
|
||||
newItems := []Favorite{}
|
||||
found := false
|
||||
for _, fav := range favorites.Items {
|
||||
if fav.Path != path {
|
||||
newItems = append(newItems, fav)
|
||||
} else {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
http.Error(w, "Favori introuvable", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Réorganiser les ordres
|
||||
for i := range newItems {
|
||||
newItems[i].Order = i
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// handleReorderFavorites réorganise l'ordre des favoris
|
||||
func (h *Handler) handleReorderFavorites(w http.ResponseWriter, r *http.Request) {
|
||||
var order []string
|
||||
if err := json.NewDecoder(r.Body).Decode(&order); err != nil {
|
||||
http.Error(w, "JSON invalide", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
favorites, err := h.loadFavorites()
|
||||
if err != nil {
|
||||
h.logger.Printf("Erreur chargement favoris: %v", err)
|
||||
http.Error(w, "Erreur de chargement", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Créer un map pour retrouver les favoris rapidement
|
||||
favMap := make(map[string]*Favorite)
|
||||
for i := range favorites.Items {
|
||||
favMap[favorites.Items[i].Path] = &favorites.Items[i]
|
||||
}
|
||||
|
||||
// Réorganiser selon le nouvel ordre
|
||||
newItems := []Favorite{}
|
||||
for i, path := range order {
|
||||
if fav, ok := favMap[path]; ok {
|
||||
fav.Order = i
|
||||
newItems = append(newItems, *fav)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
}
|
||||
|
||||
// getIcon retourne l'icône appropriée pour un fichier/dossier
|
||||
func getIcon(isDir bool, path string) string {
|
||||
if isDir {
|
||||
return "📁"
|
||||
}
|
||||
return "📄"
|
||||
}
|
||||
Reference in New Issue
Block a user