2025-01-26 22:23:42 +00:00
|
|
|
package views
|
|
|
|
|
|
|
|
|
|
import (
|
2025-11-13 14:44:24 +00:00
|
|
|
"encoding/json"
|
2025-01-26 22:23:42 +00:00
|
|
|
"log"
|
|
|
|
|
"net/http"
|
2025-07-25 13:44:21 +01:00
|
|
|
"strconv"
|
2025-11-05 09:27:08 +00:00
|
|
|
"strings"
|
2025-01-26 22:23:42 +00:00
|
|
|
|
2025-06-01 21:27:08 +01:00
|
|
|
urls "forgejo.gwairfelin.com/max/gispatcho"
|
2025-07-30 13:41:03 +01:00
|
|
|
"forgejo.gwairfelin.com/max/gonotes/internal/middleware"
|
2025-06-01 21:27:08 +01:00
|
|
|
"forgejo.gwairfelin.com/max/gonotes/internal/notes"
|
|
|
|
|
"forgejo.gwairfelin.com/max/gonotes/internal/templ"
|
2025-01-26 22:23:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var myurls urls.URLs
|
|
|
|
|
|
2025-07-30 13:41:03 +01:00
|
|
|
func addRequestContext(r *http.Request, ctx templ.Ctx) templ.Ctx {
|
|
|
|
|
return ctx
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-26 22:23:42 +00:00
|
|
|
func GetRoutes(prefix string) *http.ServeMux {
|
|
|
|
|
myurls = urls.URLs{
|
|
|
|
|
Prefix: prefix,
|
|
|
|
|
URLs: map[string]urls.URL{
|
2025-07-25 13:44:21 +01:00
|
|
|
"list": {Path: "/", Protocol: "GET", Handler: list},
|
|
|
|
|
"new": {Path: "/new", Protocol: "GET", Handler: new},
|
|
|
|
|
"view_": {Path: "/{note}", Protocol: "GET", Handler: view},
|
|
|
|
|
"view": {Path: "/{note}/", Protocol: "GET", Handler: view},
|
2025-11-05 09:27:08 +00:00
|
|
|
"setTags": {Path: "/{note}/tags/", Protocol: "POST", Handler: setTags},
|
2025-07-25 13:44:21 +01:00
|
|
|
"delete": {Path: "/{note}/delete/", Protocol: "GET", Handler: delete},
|
|
|
|
|
"edit": {Path: "/{note}/edit/", Protocol: "GET", Handler: edit},
|
2025-08-23 22:18:36 +01:00
|
|
|
"share": {Path: "/{note}/share/", Protocol: "POST", Handler: share},
|
2025-10-09 21:04:45 +01:00
|
|
|
"unshare": {Path: "/{note}/unshare/", Protocol: "POST", Handler: unshare},
|
2025-07-25 13:44:21 +01:00
|
|
|
"save": {Path: "/{note}/edit/save/", Protocol: "POST", Handler: save},
|
|
|
|
|
"togglebox": {Path: "/{note}/togglebox/", Protocol: "POST", Handler: togglebox},
|
2025-01-26 22:23:42 +00:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
return myurls.GetRouter()
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-27 22:28:18 +00:00
|
|
|
func view(w http.ResponseWriter, r *http.Request) {
|
2025-08-23 22:18:36 +01:00
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
2025-07-30 13:41:03 +01:00
|
|
|
|
2025-08-23 22:18:36 +01:00
|
|
|
uid := r.PathValue("note")
|
|
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
|
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
http.NotFound(w, r)
|
2025-01-26 22:23:42 +00:00
|
|
|
return
|
|
|
|
|
}
|
2025-08-23 22:18:36 +01:00
|
|
|
viewers := note.ViewersAsList()
|
2025-01-26 22:23:42 +00:00
|
|
|
|
2025-10-09 21:04:45 +01:00
|
|
|
context := templ.Ctx{
|
|
|
|
|
"note": note,
|
|
|
|
|
"urlEdit": myurls.Reverse("edit", urls.Repl{"note": uid}),
|
|
|
|
|
"urlDelete": myurls.Reverse("delete", urls.Repl{"note": uid}),
|
|
|
|
|
"urlNew": myurls.Reverse("new", urls.Repl{}),
|
|
|
|
|
"urlShare": myurls.Reverse("share", urls.Repl{"note": uid}),
|
|
|
|
|
"urlUnshare": myurls.Reverse("unshare", urls.Repl{"note": uid}),
|
2025-11-05 09:27:08 +00:00
|
|
|
"urlSetTags": myurls.Reverse("setTags", urls.Repl{"note": uid}),
|
2025-10-09 21:04:45 +01:00
|
|
|
"viewers": viewers,
|
2025-11-05 09:27:08 +00:00
|
|
|
"tags": strings.Join(note.Tags, " "),
|
2025-10-09 21:04:45 +01:00
|
|
|
"isOwner": user == note.Owner,
|
|
|
|
|
}
|
2025-08-23 22:18:36 +01:00
|
|
|
|
2025-01-26 22:23:42 +00:00
|
|
|
note.Render()
|
2025-08-23 22:18:36 +01:00
|
|
|
err := templ.RenderTemplate(w, r, "view.tmpl.html", context)
|
2025-01-26 22:23:42 +00:00
|
|
|
if err != nil {
|
2025-01-27 22:28:18 +00:00
|
|
|
log.Print(err.Error())
|
2025-01-26 22:23:42 +00:00
|
|
|
http.Error(w, "Couldn't load template", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-27 22:28:18 +00:00
|
|
|
func edit(w http.ResponseWriter, r *http.Request) {
|
2025-08-23 21:09:39 +01:00
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
2025-07-30 13:41:03 +01:00
|
|
|
|
2025-08-23 21:09:39 +01:00
|
|
|
uid := r.PathValue("note")
|
2025-08-23 22:18:36 +01:00
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
|
|
|
|
if !ok {
|
2025-08-23 21:09:39 +01:00
|
|
|
note = notes.NewNote("", user)
|
2025-01-26 22:23:42 +00:00
|
|
|
}
|
|
|
|
|
|
2025-08-23 21:09:39 +01:00
|
|
|
urlSave := myurls.Reverse("save", urls.Repl{"note": uid})
|
2025-06-01 21:27:08 +01:00
|
|
|
context := templ.Ctx{"note": note, "urlSave": urlSave, "text": string(note.Body)}
|
2025-08-23 22:18:36 +01:00
|
|
|
err := templ.RenderTemplate(w, r, "edit.tmpl.html", context)
|
2025-01-26 22:23:42 +00:00
|
|
|
if err != nil {
|
2025-01-27 22:28:18 +00:00
|
|
|
log.Print(err.Error())
|
2025-01-26 22:23:42 +00:00
|
|
|
http.Error(w, "Couldn't load template", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-27 22:56:50 +01:00
|
|
|
func new(w http.ResponseWriter, r *http.Request) {
|
2025-08-08 21:10:10 +01:00
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
|
|
|
|
|
2025-06-27 22:56:50 +01:00
|
|
|
title := r.FormValue("title")
|
2025-07-25 10:48:41 +01:00
|
|
|
if len(title) == 0 {
|
|
|
|
|
title = "<New Note>"
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-23 21:09:39 +01:00
|
|
|
note := notes.NewNote(title, user)
|
2025-06-27 22:56:50 +01:00
|
|
|
|
2025-08-23 21:09:39 +01:00
|
|
|
urlEdit := myurls.Reverse("edit", urls.Repl{"note": note.Uid})
|
2025-06-27 22:56:50 +01:00
|
|
|
http.Redirect(w, r, urlEdit, http.StatusFound)
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-18 21:40:42 +01:00
|
|
|
func delete(w http.ResponseWriter, r *http.Request) {
|
2025-07-31 17:02:08 +01:00
|
|
|
// user := r.Context().Value(middleware.ContextKey("user")).(string)
|
2025-07-30 13:41:03 +01:00
|
|
|
|
2025-06-27 22:56:50 +01:00
|
|
|
encodedTitle := r.PathValue("note")
|
2025-07-31 17:02:08 +01:00
|
|
|
err := notes.DeleteNote(encodedTitle)
|
2025-06-18 21:40:42 +01:00
|
|
|
if err != nil {
|
|
|
|
|
log.Print(err.Error())
|
|
|
|
|
http.Error(w, "Couldn't delete note", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-27 22:56:50 +01:00
|
|
|
urlList := myurls.Reverse("list", urls.Repl{})
|
|
|
|
|
http.Redirect(w, r, urlList, http.StatusFound)
|
2025-06-18 21:40:42 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-27 22:28:18 +00:00
|
|
|
func save(w http.ResponseWriter, r *http.Request) {
|
2025-08-08 21:10:10 +01:00
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
2025-08-23 21:09:39 +01:00
|
|
|
uid := r.PathValue("note")
|
|
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
2025-08-08 21:10:10 +01:00
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
|
http.NotFound(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-18 21:51:46 +01:00
|
|
|
title := r.FormValue("title")
|
2025-01-26 22:23:42 +00:00
|
|
|
body := r.FormValue("body")
|
2025-06-18 21:51:46 +01:00
|
|
|
|
2025-08-08 21:10:10 +01:00
|
|
|
log.Printf("About to save to note %+v", note)
|
|
|
|
|
note.Title = title
|
|
|
|
|
note.Body = []byte(body)
|
2025-01-26 22:23:42 +00:00
|
|
|
note.Save()
|
2025-06-18 21:51:46 +01:00
|
|
|
|
2025-08-23 21:09:39 +01:00
|
|
|
http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": note.Uid}), http.StatusFound)
|
2025-06-27 22:56:50 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-23 22:18:36 +01:00
|
|
|
func share(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
|
|
|
|
uid := r.PathValue("note")
|
|
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
|
|
|
|
|
2025-10-09 21:04:45 +01:00
|
|
|
if !ok || note.Owner != user {
|
2025-08-23 22:18:36 +01:00
|
|
|
http.NotFound(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
viewer := r.FormValue("viewer")
|
|
|
|
|
note.AddViewer(viewer)
|
|
|
|
|
note.Save()
|
2025-10-09 20:27:03 +01:00
|
|
|
notes.Notes.Add(note, viewer)
|
2025-08-23 22:18:36 +01:00
|
|
|
|
|
|
|
|
http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": note.Uid}), http.StatusFound)
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-09 21:04:45 +01:00
|
|
|
func unshare(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
|
|
|
|
uid := r.PathValue("note")
|
|
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
|
|
|
|
|
|
|
|
|
if !ok || note.Owner != user {
|
|
|
|
|
http.NotFound(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
viewer := r.FormValue("viewer")
|
|
|
|
|
note.DelViewer(viewer)
|
|
|
|
|
note.Save()
|
|
|
|
|
notes.Notes.Del(note, viewer)
|
|
|
|
|
|
|
|
|
|
http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": note.Uid}), http.StatusFound)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-25 13:44:21 +01:00
|
|
|
func togglebox(w http.ResponseWriter, r *http.Request) {
|
2025-08-23 22:18:36 +01:00
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
2025-07-30 13:41:03 +01:00
|
|
|
|
2025-08-23 22:18:36 +01:00
|
|
|
uid := r.PathValue("note")
|
2025-07-25 13:44:21 +01:00
|
|
|
nthBox, err := strconv.Atoi(r.FormValue("box"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal("You fucked up boy")
|
2025-11-13 14:44:24 +00:00
|
|
|
http.Error(w, "Box not provided as numeric value", 400)
|
2025-07-25 13:44:21 +01:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-23 22:18:36 +01:00
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
|
|
|
|
if !ok {
|
2025-11-13 14:44:24 +00:00
|
|
|
http.Error(w, "Note not found", 404)
|
2025-07-25 13:44:21 +01:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 14:44:24 +00:00
|
|
|
toggled, checked := note.ToggleBox(nthBox)
|
2025-07-25 13:44:21 +01:00
|
|
|
|
2025-11-13 14:44:24 +00:00
|
|
|
if !toggled {
|
|
|
|
|
http.Error(w, "Failed to toggle box", 500)
|
|
|
|
|
} else {
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
|
json.NewEncoder(w).Encode(map[string]any{"checked": checked})
|
|
|
|
|
}
|
2025-07-25 13:44:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type titleAndURL struct {
|
2025-06-27 22:56:50 +01:00
|
|
|
Title string
|
2025-07-25 13:44:21 +01:00
|
|
|
URL string
|
2025-01-26 22:23:42 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-27 22:28:18 +00:00
|
|
|
func list(w http.ResponseWriter, r *http.Request) {
|
2025-07-30 13:41:03 +01:00
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
|
|
|
|
|
2025-11-05 08:46:22 +00:00
|
|
|
tag := r.FormValue("tag")
|
|
|
|
|
|
2025-07-25 13:44:21 +01:00
|
|
|
titlesAndUrls := make([]titleAndURL, 0)
|
2025-01-27 22:28:18 +00:00
|
|
|
|
2026-01-05 20:46:32 +00:00
|
|
|
ns := notes.Notes.GetOrdered(user)
|
2025-07-31 17:02:08 +01:00
|
|
|
log.Printf("Notes: %+v", notes.Notes)
|
|
|
|
|
log.Printf("Notes for %s: %+v", user, ns)
|
2025-06-27 22:56:50 +01:00
|
|
|
|
2026-01-05 20:46:32 +00:00
|
|
|
for _, note := range ns {
|
2025-11-05 08:46:22 +00:00
|
|
|
if tag == "" || note.HasTag(tag) {
|
|
|
|
|
titlesAndUrls = append(
|
|
|
|
|
titlesAndUrls,
|
|
|
|
|
titleAndURL{Title: note.Title, URL: myurls.Reverse("view", urls.Repl{"note": note.Uid})},
|
|
|
|
|
)
|
|
|
|
|
}
|
2025-01-27 22:28:18 +00:00
|
|
|
}
|
|
|
|
|
|
2025-06-27 22:56:50 +01:00
|
|
|
urlNew := myurls.Reverse("new", urls.Repl{})
|
|
|
|
|
|
2025-07-31 17:02:08 +01:00
|
|
|
err := templ.RenderTemplate(w, r, "list.tmpl.html", templ.Ctx{"notes": titlesAndUrls, "urlNew": urlNew})
|
2025-01-27 22:28:18 +00:00
|
|
|
if err != nil {
|
|
|
|
|
log.Print(err.Error())
|
|
|
|
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-05 09:27:08 +00:00
|
|
|
|
|
|
|
|
func setTags(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
user := r.Context().Value(middleware.ContextKey("user")).(string)
|
|
|
|
|
uid := r.PathValue("note")
|
|
|
|
|
tags := r.FormValue("tags")
|
|
|
|
|
|
|
|
|
|
note, ok := notes.Notes.GetOne(user, uid)
|
|
|
|
|
if !ok || note.Owner != user {
|
|
|
|
|
http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": uid}), http.StatusFound)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
note.Tags = strings.Split(tags, " ")
|
|
|
|
|
note.Save()
|
|
|
|
|
http.Redirect(w, r, myurls.Reverse("view", urls.Repl{"note": note.Uid}), http.StatusFound)
|
|
|
|
|
}
|