300 lines
8.3 KiB
Go
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, ¬ebookFromForm)
|
||
|
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, ¬ebookFromForm)
|
||
|
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)
|
||
|
}
|
||
|
}
|