Change d'interface plus légére, modification side barre

This commit is contained in:
2025-12-24 16:14:17 +01:00
parent cc1d6880a7
commit 917a31d5a8
46 changed files with 7484 additions and 298 deletions

View File

@ -71,6 +71,16 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
// Public endpoints
if path == "/api/public/list" {
h.handlePublicList(w, r)
return
}
if path == "/api/public/toggle" {
h.handlePublicToggle(w, r)
return
}
// Legacy/HTML endpoints
if strings.HasPrefix(path, "/api/search") {
h.handleSearch(w, r)
@ -295,12 +305,14 @@ func (h *Handler) handleHome(w http.ResponseWriter, r *http.Request) {
Filename string
Content string
IsHome bool
IsPublic bool
Backlinks []BacklinkInfo
Breadcrumb template.HTML
}{
Filename: "🏠 Accueil - Index",
Content: content,
IsHome: true,
IsPublic: false,
Backlinks: nil, // Pas de backlinks pour la page d'accueil
Breadcrumb: h.generateBreadcrumb(""),
}
@ -351,7 +363,10 @@ func (h *Handler) generateHomeMarkdown(r *http.Request) string {
// Section des favoris (après les tags)
h.generateFavoritesSection(&sb, r)
// Section des notes récemment modifiées (après les favoris)
// Section des notes publiques (après les favoris)
h.generatePublicNotesSection(&sb, r)
// Section des notes récemment modifiées (après les notes publiques)
h.generateRecentNotesSection(&sb, r)
// Section de toutes les notes avec accordéon
@ -380,7 +395,7 @@ func (h *Handler) generateTagsSection(sb *strings.Builder) {
sb.WriteString("<div class=\"home-section\">\n")
sb.WriteString(" <div class=\"home-section-header\" onclick=\"toggleFolder('tags')\">\n")
sb.WriteString(" <h2 class=\"home-section-title\">🏷️ Tags</h2>\n")
sb.WriteString(" <h2 class=\"home-section-title\"><i data-lucide=\"tags\" class=\"icon-sm\"></i> Tags</h2>\n")
sb.WriteString(" </div>\n")
sb.WriteString(" <div class=\"home-section-content\" id=\"folder-tags\">\n")
sb.WriteString(" <div class=\"tags-cloud\">\n")
@ -408,7 +423,7 @@ func (h *Handler) generateFavoritesSection(sb *strings.Builder, r *http.Request)
sb.WriteString("<div class=\"home-section\">\n")
sb.WriteString(" <div class=\"home-section-header\" onclick=\"toggleFolder('favorites')\">\n")
sb.WriteString(" <h2 class=\"home-section-title\"> " + h.t(r, "favorites.title") + "</h2>\n")
sb.WriteString(" <h2 class=\"home-section-title\"><i data-lucide=\"star\" class=\"icon-sm\"></i> " + h.t(r, "favorites.title") + "</h2>\n")
sb.WriteString(" </div>\n")
sb.WriteString(" <div class=\"home-section-content\" id=\"folder-favorites\">\n")
sb.WriteString(" <div class=\"note-tree favorites-tree\">\n")
@ -420,7 +435,7 @@ func (h *Handler) generateFavoritesSection(sb *strings.Builder, r *http.Request)
// Dossier - avec accordéon
sb.WriteString(fmt.Sprintf(" <div class=\"folder indent-level-1\">\n"))
sb.WriteString(fmt.Sprintf(" <div class=\"folder-header\" onclick=\"toggleFolder('%s')\">\n", safeID))
sb.WriteString(fmt.Sprintf(" <span class=\"folder-icon\" id=\"icon-%s\">📁</span>\n", safeID))
sb.WriteString(fmt.Sprintf(" <span class=\"folder-icon\" id=\"icon-%s\"><i data-lucide=\"folder\" class=\"icon-sm\"></i></span>\n", safeID))
sb.WriteString(fmt.Sprintf(" <strong>%s</strong>\n", fav.Title))
sb.WriteString(fmt.Sprintf(" </div>\n"))
sb.WriteString(fmt.Sprintf(" <div class=\"folder-content\" id=\"folder-%s\">\n", safeID))
@ -445,6 +460,44 @@ func (h *Handler) generateFavoritesSection(sb *strings.Builder, r *http.Request)
sb.WriteString("</div>\n\n")
}
// generatePublicNotesSection génère la section des notes publiques
func (h *Handler) generatePublicNotesSection(sb *strings.Builder, r *http.Request) {
publicNotes, err := h.loadPublicNotes()
if err != nil || len(publicNotes.Notes) == 0 {
return
}
sb.WriteString("<div class=\"home-section\">\n")
sb.WriteString(" <div class=\"home-section-header\" onclick=\"toggleFolder('public-notes')\">\n")
sb.WriteString(fmt.Sprintf(" <h2 class=\"home-section-title\"><i data-lucide=\"globe\" class=\"icon-sm\"></i> %s (%d)</h2>\n", h.t(r, "publicNotes.title"), len(publicNotes.Notes)))
sb.WriteString(" </div>\n")
sb.WriteString(" <div class=\"home-section-content\" id=\"folder-public-notes\">\n")
sb.WriteString(" <div class=\"public-notes-list\">\n")
for _, note := range publicNotes.Notes {
filename := filepath.Base(note.Path)
htmlFile := filename[:len(filename)-3] + ".html"
publicURL := fmt.Sprintf("/public/%s", htmlFile)
sb.WriteString(" <div class=\"public-note-card\">\n")
sb.WriteString(fmt.Sprintf(" <div class=\"public-note-header\">\n"))
sb.WriteString(fmt.Sprintf(" <a href=\"#\" class=\"public-note-edit\" hx-get=\"/api/notes/%s\" hx-target=\"#editor-container\" hx-swap=\"innerHTML\" hx-push-url=\"true\" title=\"%s\">", note.Path, h.t(r, "publicNotes.editNote")))
sb.WriteString(fmt.Sprintf(" <span class=\"public-note-title\">%s</span>", note.Title))
sb.WriteString(" </a>\n")
sb.WriteString(fmt.Sprintf(" <a href=\"%s\" target=\"_blank\" class=\"public-note-view\" title=\"%s\">🌐</a>\n", publicURL, h.t(r, "publicNotes.viewPublic")))
sb.WriteString(" </div>\n")
sb.WriteString(fmt.Sprintf(" <div class=\"public-note-meta\">\n"))
sb.WriteString(fmt.Sprintf(" <span class=\"public-note-source\">📄 %s</span>\n", note.Path))
sb.WriteString(fmt.Sprintf(" <span class=\"public-note-date\"><i data-lucide=\"calendar\" class=\"icon-sm\"></i> %s</span>\n", note.PublishedAt.Format("02/01/2006")))
sb.WriteString(" </div>\n")
sb.WriteString(" </div>\n")
}
sb.WriteString(" </div>\n")
sb.WriteString(" </div>\n")
sb.WriteString("</div>\n\n")
}
// generateRecentNotesSection génère la section des notes récemment modifiées
func (h *Handler) generateRecentNotesSection(sb *strings.Builder, r *http.Request) {
recentDocs := h.idx.GetRecentDocuments(5)
@ -477,7 +530,7 @@ func (h *Handler) generateRecentNotesSection(sb *strings.Builder, r *http.Reques
sb.WriteString(fmt.Sprintf(" <a href=\"#\" class=\"recent-note-link\" hx-get=\"/api/notes/%s\" hx-target=\"#editor-container\" hx-swap=\"innerHTML\" hx-push-url=\"true\">\n", doc.Path))
sb.WriteString(fmt.Sprintf(" <div class=\"recent-note-title\">%s</div>\n", doc.Title))
sb.WriteString(fmt.Sprintf(" <div class=\"recent-note-meta\">\n"))
sb.WriteString(fmt.Sprintf(" <span class=\"recent-note-date\">📅 %s</span>\n", dateStr))
sb.WriteString(fmt.Sprintf(" <span class=\"recent-note-date\"><i data-lucide=\"calendar\" class=\"icon-sm\"></i> %s</span>\n", dateStr))
if len(doc.Tags) > 0 {
sb.WriteString(fmt.Sprintf(" <span class=\"recent-note-tags\">"))
for i, tag := range doc.Tags {
@ -523,7 +576,7 @@ func (h *Handler) generateFavoriteFolderContent(sb *strings.Builder, folderPath
// Sous-dossier
sb.WriteString(fmt.Sprintf("%s<div class=\"folder %s\">\n", indent, indentClass))
sb.WriteString(fmt.Sprintf("%s <div class=\"folder-header\" onclick=\"toggleFolder('%s')\">\n", indent, safeID))
sb.WriteString(fmt.Sprintf("%s <span class=\"folder-icon\" id=\"icon-%s\">📁</span>\n", indent, safeID))
sb.WriteString(fmt.Sprintf("%s <span class=\"folder-icon\" id=\"icon-%s\"><i data-lucide=\"folder\" class=\"icon-sm\"></i></span>\n", indent, safeID))
sb.WriteString(fmt.Sprintf("%s <strong>%s</strong>\n", indent, name))
sb.WriteString(fmt.Sprintf("%s </div>\n", indent))
sb.WriteString(fmt.Sprintf("%s <div class=\"folder-content\" id=\"folder-%s\">\n", indent, safeID))
@ -579,7 +632,7 @@ func (h *Handler) generateMarkdownTree(sb *strings.Builder, node *TreeNode, dept
indentClass := fmt.Sprintf("indent-level-%d", depth)
sb.WriteString(fmt.Sprintf("%s<div class=\"folder %s\">\n", indent, indentClass))
sb.WriteString(fmt.Sprintf("%s <div class=\"folder-header\" onclick=\"toggleFolder('%s')\">\n", indent, safeID))
sb.WriteString(fmt.Sprintf("%s <span class=\"folder-icon\" id=\"icon-%s\">📁</span>\n", indent, safeID))
sb.WriteString(fmt.Sprintf("%s <span class=\"folder-icon\" id=\"icon-%s\"><i data-lucide=\"folder\" class=\"icon-sm\"></i></span>\n", indent, safeID))
sb.WriteString(fmt.Sprintf("%s <strong>%s</strong>\n", indent, node.Name))
sb.WriteString(fmt.Sprintf("%s </div>\n", indent))
sb.WriteString(fmt.Sprintf("%s <div class=\"folder-content\" id=\"folder-%s\">\n", indent, safeID))
@ -688,12 +741,14 @@ func (h *Handler) createAndRenderNote(w http.ResponseWriter, r *http.Request, fi
Filename string
Content string
IsHome bool
IsPublic bool
Backlinks []BacklinkInfo
}{
Filename: filename,
Content: initialContent,
IsHome: false,
Backlinks: nil, // Pas de backlinks pour une nouvelle note
IsPublic: false, // Nouvelle note, pas publique par défaut
Backlinks: nil, // Pas de backlinks pour une nouvelle note
}
err = h.templates.ExecuteTemplate(w, "editor.html", data)
@ -832,12 +887,14 @@ func (h *Handler) handleGetNote(w http.ResponseWriter, r *http.Request, filename
Filename string
Content string
IsHome bool
IsPublic bool
Backlinks []BacklinkInfo
Breadcrumb template.HTML
}{
Filename: filename,
Content: string(content),
IsHome: false,
IsPublic: h.isPublic(filename),
Backlinks: backlinkData,
Breadcrumb: h.generateBreadcrumb(filename),
}
@ -1347,15 +1404,17 @@ func (h *Handler) handleFolderView(w http.ResponseWriter, r *http.Request) {
// Utiliser le template editor.html
data := struct {
Filename string
Content string
IsHome bool
Backlinks []BacklinkInfo
Filename string
Content string
IsHome bool
IsPublic bool
Backlinks []BacklinkInfo
Breadcrumb template.HTML
}{
Filename: cleanPath,
Content: content,
IsHome: true, // Pas d'édition pour une vue de dossier
IsPublic: false,
Backlinks: nil,
Breadcrumb: h.generateBreadcrumb(cleanPath),
}
@ -1370,7 +1429,7 @@ func (h *Handler) handleFolderView(w http.ResponseWriter, r *http.Request) {
// generateBreadcrumb génère un fil d'Ariane HTML cliquable
func (h *Handler) generateBreadcrumb(path string) template.HTML {
if path == "" {
return template.HTML(`<strong>📁 Racine</strong>`)
return template.HTML(`<strong><i data-lucide="folder" class="icon-sm"></i> Racine</strong>`)
}
parts := strings.Split(filepath.ToSlash(path), "/")
@ -1379,7 +1438,7 @@ func (h *Handler) generateBreadcrumb(path string) template.HTML {
sb.WriteString(`<span class="breadcrumb">`)
// Lien racine
sb.WriteString(`<a href="#" hx-get="/api/home" hx-target="#editor-container" hx-swap="innerHTML" hx-push-url="true" class="breadcrumb-link">📁 Racine</a>`)
sb.WriteString(`<a href="#" hx-get="/api/home" hx-target="#editor-container" hx-swap="innerHTML" hx-push-url="true" class="breadcrumb-link"><i data-lucide="folder" class="icon-sm"></i> Racine</a>`)
// Construire les liens pour chaque partie
currentPath := ""