feat: layout mobile, abas múltiplas e categorias em árvore
- Responsivo ≤760px: sidebar vira gaveta com backdrop, painel de versões em tela cheia, toolbar/menu rolam sem rótulos, alvos de toque, dvh + safe-area, fonte do editor ≥16px (anti-zoom iOS) - Abas: várias notas abertas com estado sujo por aba, ✕ com confirmação, clique do meio, Alt+W / Alt+←/→ / Alt+1..9; abas e rascunhos sobrevivem à sessão via localStorage - Categorias: modelo vira árvore (categories.json) com notas em múltiplas categorias; explorador no sidebar com expandir/renomear/mover/excluir (sem ciclos, GC de vínculos) e seletor multi-marca no editor; filtro por pasta recursivo por padrão; migração automática do campo único legado - API: POST/PUT/DELETE /api/categories; notas aceitam categories: [ids] - Testes: store (árvore, ciclo, migração, GC) e api (CRUD de categorias)
This commit is contained in:
1 parent
9bc5de4c56
commit
7e89207b70
10 files changed
+1737
-489
No files matched your search
+18
-16
@@ -22,20 +22,20 @@ func (s *Server) serveIndex(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// noteInput é o corpo aceito por POST/PUT de notas.
|
||||
type noteInput struct {
|
||||
Title string `json:"title"`
|
||||
Format string `json:"format"`
|
||||
Category string `json:"category"`
|
||||
Content string `json:"content"`
|
||||
Author string `json:"author"`
|
||||
Message string `json:"message"`
|
||||
Title string `json:"title"`
|
||||
Format string `json:"format"`
|
||||
Categories []string `json:"categories"` // IDs da árvore de categorias
|
||||
Content string `json:"content"`
|
||||
Author string `json:"author"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (in noteInput) fields() (string, string, string, string, string, string) {
|
||||
func (in noteInput) fields() (string, string, []string, string, string, string) {
|
||||
f := in.Format
|
||||
if f == "" {
|
||||
f = store.FormatTxt
|
||||
}
|
||||
return in.Title, f, in.Category, in.Content, in.Author, in.Message
|
||||
return in.Title, f, in.Categories, in.Content, in.Author, in.Message
|
||||
}
|
||||
|
||||
// noteView é a representação completa (meta + conteúdo) de uma nota.
|
||||
@@ -46,10 +46,12 @@ type noteView struct {
|
||||
|
||||
func (s *Server) handleListNotes(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
recursive := q.Get("recursive") != "0"
|
||||
notes, err := s.st.List(store.Filter{
|
||||
Category: q.Get("category"),
|
||||
Tag: q.Get("tag"),
|
||||
Query: q.Get("q"),
|
||||
Category: q.Get("category"),
|
||||
Recursive: recursive,
|
||||
Tag: q.Get("tag"),
|
||||
Query: q.Get("q"),
|
||||
})
|
||||
if err != nil {
|
||||
mapStoreError(w, err)
|
||||
@@ -67,8 +69,8 @@ func (s *Server) handleCreateNote(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusBadRequest, "corpo JSON inválido")
|
||||
return
|
||||
}
|
||||
title, format, category, content, author, message := in.fields()
|
||||
n, err := s.st.Create(title, format, category, content, author, message)
|
||||
title, format, categories, content, author, message := in.fields()
|
||||
n, err := s.st.Create(title, format, categories, content, author, message)
|
||||
if err != nil {
|
||||
mapStoreError(w, err)
|
||||
return
|
||||
@@ -91,8 +93,8 @@ func (s *Server) handleUpdateNote(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusBadRequest, "corpo JSON inválido")
|
||||
return
|
||||
}
|
||||
title, format, category, content, author, message := in.fields()
|
||||
n, err := s.st.Update(r.PathValue("id"), title, format, category, content, author, message)
|
||||
title, format, categories, content, author, message := in.fields()
|
||||
n, err := s.st.Update(r.PathValue("id"), title, format, categories, content, author, message)
|
||||
if err != nil {
|
||||
mapStoreError(w, err)
|
||||
return
|
||||
@@ -159,7 +161,7 @@ func (s *Server) handleCategories(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if cats == nil {
|
||||
cats = []store.CatCount{}
|
||||
cats = []store.CategoryView{}
|
||||
}
|
||||
writeJSON(w, http.StatusOK, cats)
|
||||
}
|
||||
Reference in new issue
Block a user