From b2945594924d45ca2a547c9249da450c7c9627a7 Mon Sep 17 00:00:00 2001
From: roberto
Date: Sun, 9 Mar 2025 17:07:49 +0100
Subject: [PATCH] Item sharing edit form
---
assets/static/js/main.js | 16 +++++-
assets/templates/items/share.tmpl | 7 +--
assets/templates/items/share_edit.tmpl | 52 +++++++++++++++++++
assets/templates/items/shares.tmpl | 7 ++-
cmd/web/items_handlers.go | 71 ++++++++++++++++++++++++--
cmd/web/routes.go | 1 +
models/constructors.go | 4 ++
models/itemshare.go | 34 +++++++++++-
8 files changed, 179 insertions(+), 13 deletions(-)
create mode 100644 assets/templates/items/share_edit.tmpl
diff --git a/assets/static/js/main.js b/assets/static/js/main.js
index e9221b5..e885101 100644
--- a/assets/static/js/main.js
+++ b/assets/static/js/main.js
@@ -186,7 +186,13 @@ function bm_type_field_undelete(sender, type_field_id) {
function bm_element_list_delete(sender, element_name, element_name_remove) {
document.getElementById(element_name_remove).value = '1';
sender.hidden = true;
- document.getElementById('Undelete-' + element_name).hidden = false;
+
+ let btn = document.getElementById('Undelete-' + element_name);
+ if(btn !== null) btn.hidden = false;
+
+ btn = document.getElementById('Edit-' + element_name);
+ if(btn !== null) btn.hidden = true;
+
let x = document.getElementsByClassName(element_name + "-Col");
for (let i = 0; i < x.length; i++) {
x[i].classList.add("field-opaque");
@@ -196,7 +202,13 @@ function bm_element_list_delete(sender, element_name, element_name_remove) {
function bm_element_list_undelete(sender, element_name, element_name_remove) {
document.getElementById(element_name_remove).value = '';
sender.hidden = true;
- document.getElementById('Delete-' + element_name).hidden = false;
+
+ let btn = document.getElementById('Delete-' + element_name);
+ if(btn !== null) btn.hidden = false;
+
+ btn = document.getElementById('Edit-' + element_name);
+ if(btn !== null) btn.hidden = false;
+
let x = document.getElementsByClassName(element_name + "-Col");
for (let i = 0; i < x.length; i++) {
x[i].classList.remove("field-opaque");
diff --git a/assets/templates/items/share.tmpl b/assets/templates/items/share.tmpl
index f81d4d5..6ffbd96 100644
--- a/assets/templates/items/share.tmpl
+++ b/assets/templates/items/share.tmpl
@@ -40,12 +40,9 @@
-
+ {{ widget_checkbox "Permission_edit" "Allow editing" "1" "" }}
+
diff --git a/assets/templates/items/share_edit.tmpl b/assets/templates/items/share_edit.tmpl
new file mode 100644
index 0000000..64365eb
--- /dev/null
+++ b/assets/templates/items/share_edit.tmpl
@@ -0,0 +1,52 @@
+{{define "page:content"}}
+
+ {{ end }}
\ No newline at end of file
diff --git a/assets/templates/items/shares.tmpl b/assets/templates/items/shares.tmpl
index cd8cc70..f8e6f21 100644
--- a/assets/templates/items/shares.tmpl
+++ b/assets/templates/items/shares.tmpl
@@ -19,7 +19,11 @@
- {{ .PermissionEdit }}
+ {{ if eq .PermissionEdit 1}}
+
+ {{ else }}
+
+ {{ end }}
|
{{ .StartDatetime }}
@@ -30,6 +34,7 @@
|
+
|
{{ end }}
diff --git a/cmd/web/items_handlers.go b/cmd/web/items_handlers.go
index 1fa9806..f80795d 100644
--- a/cmd/web/items_handlers.go
+++ b/cmd/web/items_handlers.go
@@ -965,8 +965,8 @@ func (app *application) itemShare(w http.ResponseWriter, r *http.Request) {
EndDatetime: itemShareFromForm.EndDatetime,
}
- itemshareModel := &models.ItemShareModel{DB: app.db}
- _, err = itemshareModel.Create(itemShare)
+ itemShareModel := models.NewItemShareModel(app.db)
+ _, err = itemShareModel.Create(itemShare)
if err != nil {
app.badRequest(w, err)
return
@@ -975,14 +975,77 @@ func (app *application) itemShare(w http.ResponseWriter, r *http.Request) {
dataMessage := make(map[string]string)
dataMessage["messageType"] = "success"
- dataMessage["messageContent"] = "Item shared successfully"
+ dataMessage["messageContent"] = "Item shared created successfully"
err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage)
if err != nil {
app.serverError(w, r, err)
}
w.Header().Add("HX-Reswap", `beforeend`)
- w.Header().Add("HX-Trigger-After-Settle", `{"showMessage": "", "closeModalDialog": ""}`)
+ w.Header().Add("HX-Trigger-After-Swap", `{"showMessage": "", "closeModalDialog": ""}`)
+
+ fullBuf.WriteTo(w)
+ }
+}
+
+func (app *application) itemShareEdit(w http.ResponseWriter, r *http.Request) {
+ itemShareModel := models.NewItemShareModel(app.db)
+ id, _ := strconv.ParseInt(flow.Param(r.Context(), "id"), 10, 64)
+ itemShare, _, _ := itemShareModel.One(id)
+
+ data := app.newTemplateData(r)
+ data["itemShare"] = itemShare
+ data["baseUrl"] = app.config.baseURL
+
+ switch r.Method {
+ case http.MethodGet:
+ var fullBuf = new(bytes.Buffer)
+
+ err := response.HXFragment(fullBuf, []string{"items/share_edit.tmpl"}, "page:content", data)
+ if err != nil {
+ app.serverError(w, r, err)
+ }
+
+ w.Header().Add("HX-Trigger-After-Swap", `{"showModalDialog": ""}`)
+ fullBuf.WriteTo(w)
+ case http.MethodPost:
+ var itemShareFromForm itemShareForm
+
+ err := request.DecodePostForm(r, &itemShareFromForm)
+ if err != nil {
+ app.serverError(w, r, err)
+ }
+
+ if !itemShareFromForm.Validate(w, r, app, data) {
+ return
+ }
+
+ itemShare := &models.ItemShare{
+ Token: itemShareFromForm.Token,
+ Password: itemShareFromForm.Password,
+ PermissionEdit: itemShareFromForm.PermissionEdit,
+ StartDatetime: itemShareFromForm.StartDatetime,
+ EndDatetime: itemShareFromForm.EndDatetime,
+ }
+ itemShare.Id = id
+
+ err = itemShareModel.Update(itemShare)
+ if err != nil {
+ app.badRequest(w, err)
+ return
+ }
+ var fullBuf = new(bytes.Buffer)
+
+ dataMessage := make(map[string]string)
+ dataMessage["messageType"] = "success"
+ dataMessage["messageContent"] = "Item shared edited successfully"
+ err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", dataMessage)
+ if err != nil {
+ app.serverError(w, r, err)
+ }
+
+ w.Header().Add("HX-Reswap", `beforeend`)
+ w.Header().Add("HX-Trigger-After-Swap", `{"showMessage": "", "closeModalDialog": ""}`)
fullBuf.WriteTo(w)
}
diff --git a/cmd/web/routes.go b/cmd/web/routes.go
index 1f71a47..6f464b4 100644
--- a/cmd/web/routes.go
+++ b/cmd/web/routes.go
@@ -53,6 +53,7 @@ func (app *application) routes() http.Handler {
mux.HandleFunc("/item/update/:item_id", app.itemUpdate, "GET", "POST")
mux.HandleFunc("/item/delete/:item_id", app.itemDelete, "DELETE")
mux.HandleFunc("/item/share/:item_id", app.itemShare, "GET", "POST")
+ mux.HandleFunc("/item/share/edit/:id", app.itemShareEdit, "GET", "POST")
mux.HandleFunc("/item/add-to-dashboard/:item_id", app.itemAddToDashboard, "POST")
mux.HandleFunc("/item/remove-from-dashboard/:item_id", app.itemRemoveFromDashboard, "POST", "DELETE")
diff --git a/models/constructors.go b/models/constructors.go
index f581078..049e2d4 100644
--- a/models/constructors.go
+++ b/models/constructors.go
@@ -11,3 +11,7 @@ func NewQuicknoteModel(db *database.DB) *QuicknoteModel {
func NewItemModel(db *database.DB) *ItemModel {
return &ItemModel{BaseModel: &BaseModel{db}}
}
+
+func NewItemShareModel(db *database.DB) *ItemShareModel {
+ return &ItemShareModel{BaseModel: &BaseModel{db}}
+}
diff --git a/models/itemshare.go b/models/itemshare.go
index 02a1c74..f2e3c5c 100644
--- a/models/itemshare.go
+++ b/models/itemshare.go
@@ -7,7 +7,7 @@ import (
)
type ItemShareModel struct {
- DB *database.DB
+ *BaseModel
}
type ItemShare struct {
@@ -18,6 +18,24 @@ type ItemShare struct {
StartDatetime string `db:"start_datetime"`
EndDatetime string `db:"end_datetime"`
Password string `db:"password"`
+ ItemTitle string `db:"item_title"`
+}
+
+func (model *ItemShareModel) One(id int64) (*ItemShare, bool, error) {
+ ctx, cancel := database.GetContext()
+ defer cancel()
+
+ var row ItemShare
+
+ query := `SELECT bmi.title AS item_title, bmis.* FROM bm_item_shares bmis
+ INNER JOIN bm_item bmi ON bmis.item_id=bmi.id WHERE bmis.id = $1`
+
+ err := model.DB.GetContext(ctx, &row, query, id)
+ if errors.Is(err, sql.ErrNoRows) {
+ return nil, false, nil
+ }
+
+ return &row, true, err
}
func (model *ItemShareModel) Create(ItemShare *ItemShare) (int64, error) {
@@ -39,6 +57,20 @@ func (model *ItemShareModel) Create(ItemShare *ItemShare) (int64, error) {
return id, err
}
+func (model *ItemShareModel) Update(ItemShare *ItemShare) error {
+ ctx, cancel := database.GetContext()
+ defer cancel()
+
+ query := `UPDATE bm_item_shares SET token=:token, permission_edit=:permission_edit, start_datetime=:start_datetime, end_datetime=:end_datetime WHERE id = :id`
+ _, err := model.DB.NamedExecContext(ctx, query, ItemShare)
+
+ if err != nil {
+ return err
+ }
+
+ return err
+}
+
func (model *ItemShareModel) Delete(id int) (bool, error) {
ctx, cancel := database.GetContext()
defer cancel()