BrainMinder/cmd/web/notebooks_handlers.go
2024-08-22 10:13:16 +02:00

300 lines
8.3 KiB
Go

package main
import (
"bytes"
"fmt"
"net/http"
"strconv"
"brainminder.speedtech.it/internal/request"
"brainminder.speedtech.it/internal/response"
"brainminder.speedtech.it/internal/validator"
"brainminder.speedtech.it/models"
"github.com/alexedwards/flow"
)
type notebookForm struct {
Id int64 `form:"Id"`
Title string `form:"Title"`
Icon string `form:"Icon"`
Description string `form:"Description"`
Fields []models.Field
Widgets []models.Widget
Validator validator.Validator `form:"-"`
}
func (form *notebookForm) Validate(w http.ResponseWriter, r *http.Request, app *application, data map[string]any) bool {
var fullBuf = new(bytes.Buffer)
form.Validator.CheckField(form.Title != "", "Title", "Title is required")
form.Validator.CheckField(form.Description != "", "Description", "Description is required")
if form.Validator.HasErrors() {
w.Header().Add("HX-Retarget", "#message")
data["messageType"] = "failure"
data["messageContent"] = "Impossible to save the notebook"
data["messageFieldErrors"] = form.Validator.FieldErrors
buf, err := response.Fragment([]string{"partials/message.tmpl"}, "message", data)
if err != nil {
app.serverError(w, r, err)
}
fullBuf.Write(buf.Bytes())
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity)
return false
}
return true
}
func (app *application) notebooks(w http.ResponseWriter, r *http.Request) {
data := app.newTemplateData(r)
notebookModel := &models.NotebookModel{DB: app.db}
var fullBuf = new(bytes.Buffer)
rows, _, _ := notebookModel.All()
data["notebooks"] = &rows
if r.Header.Get("HX-Request") == "true" {
err := response.HXFragment(fullBuf, []string{"notebooks/list.tmpl"}, "notebooks:list", data)
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteString("<div hx-swap-oob=\"true\" id=\"page-title\">")
err = response.HXFragmentOOB(fullBuf, []string{"notebooks/list_title.tmpl"}, "page:title", data, "page-title")
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteTo(w)
} else {
err := response.Page(w, http.StatusOK, data, []string{"notebooks/index.tmpl", "notebooks/list.tmpl", "notebooks/list_title.tmpl"})
if err != nil {
app.serverError(w, r, err)
}
}
w.WriteHeader(http.StatusOK)
}
func (app *application) notebookCreate(w http.ResponseWriter, r *http.Request) {
notebookModel := &models.NotebookModel{DB: app.db}
var fullBuf = new(bytes.Buffer)
var notebook_id int64
data := app.newTemplateData(r)
data["formAction"] = "/notebook/create"
data["formTarget"] = "#page-content"
switch r.Method {
case http.MethodGet:
data["notebook"] = notebookForm{
Title: "",
Icon: "",
Description: "",
}
if r.Header.Get("HX-Request") == "true" {
err := response.HXFragment(fullBuf, []string{"notebooks/form.tmpl"}, "page:content", data)
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteString("<div hx-swap-oob=\"true\" id=\"page-title\">")
err = response.HXFragmentOOB(fullBuf, []string{"notebooks/create_title.tmpl"}, "page:title", data, "page-title")
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteTo(w)
} else {
err := response.Page(w, http.StatusOK, data, []string{"notebooks/create_title.tmpl", "notebooks/form.tmpl"})
if err != nil {
app.serverError(w, r, err)
}
}
case http.MethodPost:
var notebookFromForm notebookForm
err := request.DecodePostForm(r, &notebookFromForm)
if err != nil {
app.serverError(w, r, err)
}
if !notebookFromForm.Validate(w, r, app, data) {
return
}
notebook := &models.Notebook{
Title: notebookFromForm.Title,
Icon: notebookFromForm.Icon,
Description: notebookFromForm.Description,
}
notebook_id, err = notebookModel.Create(notebook)
if err != nil {
app.badRequest(w, err)
return
}
data["formAction"] = fmt.Sprint("/notebook/update/", notebook_id)
data["formTarget"] = "#message"
data["notebook"] = notebookForm{
Id: notebook_id,
Title: notebook.Title,
Icon: notebook.Icon,
Description: notebook.Description,
}
err = response.HXFragment(fullBuf, []string{"notebooks/form.tmpl"}, "page:content", data)
if err != nil {
app.serverError(w, r, err)
}
err = response.HXFragmentOOB(fullBuf, []string{"notebooks/update_title.tmpl"}, "page:title", data, "page-title")
if err != nil {
app.serverError(w, r, err)
}
notebookModel := &models.NotebookModel{DB: app.db}
data["notebooksList"] = notebookModel.AllAsOptions(true)
err = response.HXFragmentOOB(fullBuf, []string{"partials/notebooks-list.tmpl"}, "partial:notebooks-list", data, "current_notebook_id")
if err != nil {
app.serverError(w, r, err)
}
dataMessage := make(map[string]string)
dataMessage["messageType"] = "success"
dataMessage["messageContent"] = "Notebook created successfully"
err = response.HXFragmentOOB(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage, "message")
if err != nil {
app.serverError(w, r, err)
}
w.Header().Add("HX-Replace-Url", fmt.Sprint("/notebook/update/", notebook_id))
fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity)
}
}
func (app *application) notebookUpdate(w http.ResponseWriter, r *http.Request) {
notebookModel := &models.NotebookModel{DB: app.db}
notebook_id_str := flow.Param(r.Context(), "notebook_id")
notebook_id, _ := strconv.ParseInt(notebook_id_str, 10, 64)
notebook, _, _ := notebookModel.One(notebook_id)
data := app.newTemplateData(r)
data["formAction"] = "/notebook/update/" + notebook_id_str
data["formTarget"] = "#message"
var fullBuf = new(bytes.Buffer)
switch r.Method {
case http.MethodGet:
data["notebook"] = notebookForm{
Id: notebook.Id,
Title: notebook.Title,
Icon: notebook.Icon,
Description: notebook.Description,
}
if r.Header.Get("HX-Request") == "true" {
err := response.HXFragment(fullBuf, []string{"notebooks/form.tmpl"}, "page:content", data)
if err != nil {
app.serverError(w, r, err)
}
err = response.HXFragmentOOB(fullBuf, []string{"notebooks/update_title.tmpl"}, "page:title", data, "page-title")
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteTo(w)
} else {
err := response.Page(w, http.StatusOK, data, []string{"notebooks/update_title.tmpl", "notebooks/form.tmpl"})
if err != nil {
app.serverError(w, r, err)
}
}
case http.MethodPost:
var notebookFromForm notebookForm
err := request.DecodePostForm(r, &notebookFromForm)
if err != nil {
app.serverError(w, r, err)
}
if !notebookFromForm.Validate(w, r, app, data) {
return
}
notebook.Title = notebookFromForm.Title
notebook.Description = notebookFromForm.Description
notebook.Icon = notebookFromForm.Icon
err = notebookModel.Update(notebook)
if err != nil {
app.badRequest(w, err)
return
}
data["notebook"] = notebookForm{
Id: notebook.Id,
Title: notebook.Title,
Icon: notebook.Icon,
Description: notebook.Description,
}
dataMessage := make(map[string]string)
dataMessage["messageType"] = "success"
dataMessage["messageContent"] = "Notebook saved successfully"
err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage)
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteString("<div hx-swap-oob=\"true\" id=\"page-title\">")
err = response.HXFragmentOOB(fullBuf, []string{"notebooks/update_title.tmpl"}, "page:title", data, "page-title")
if err != nil {
app.serverError(w, r, err)
}
notebookModel := &models.NotebookModel{DB: app.db}
data["notebooksList"] = notebookModel.AllAsOptions(true)
err = response.HXFragmentOOB(fullBuf, []string{"partials/notebooks-list.tmpl"}, "partial:notebooks-list", data, "current_notebook_id")
if err != nil {
app.serverError(w, r, err)
}
fullBuf.WriteTo(w)
w.WriteHeader(http.StatusUnprocessableEntity)
}
}
func (app *application) notebookDelete(w http.ResponseWriter, r *http.Request) {
notebookModel := &models.NotebookModel{DB: app.db}
notebook_id_str := flow.Param(r.Context(), "notebook_id")
notebook_id, _ := strconv.ParseInt(notebook_id_str, 10, 64)
_, err := notebookModel.Delete(notebook_id)
if err != nil {
app.serverError(w, r, err)
}
}