Item sharing edit form

This commit is contained in:
roberto 2025-03-09 17:07:49 +01:00
parent da4b023aa7
commit b294559492
8 changed files with 179 additions and 13 deletions

View file

@ -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");

View file

@ -40,12 +40,9 @@
</p>
</div>
</div>
<fieldset>
<legend>Permissions</legend>
<div class="row">
<div class="col l6">{{ widget_checkbox "Permission_edit" "Edit" "1" "" }}</div>
</div>
</fieldset>
<div class="col l6"><p>{{ widget_checkbox "Permission_edit" "Allow editing" "1" "" }}</p></div>
</div>
<div id="footer-navbar">
<button type="submit" class="main" title="Share"><i class='bi bi-share-fill'></i><span>Share</span></button>
</div>

View file

@ -0,0 +1,52 @@
{{define "page:content"}}
<dialog id="dialog" class="share">
<header>
<h5><i class="bi bi-share-fill" title="Share"></i> Share item</h5>
<span class="close-dialog button close"><i class='close-dialog bi bi-x-circle-fill'></i></span>
</header>
<div class="content">
<form hx-post="/item/share/edit/{{ .itemShare.Id }}" hx-target="#message">
<h5>{{ .itemShare.ItemTitle }}</h5>
<div class="row">
<div class="col l6">
<p style="margin-right: 6px">
<label for="share-start-datetime">Start date time</label>
<input name="Start_datetime" id="share-start-datetime" type="datetime-local" value="{{ .itemShare.StartDatetime }}"/>
</p>
</div>
<div class="col l6">
<p>
<label for="share-end-datetime">End date time</label>
<input name="End_datetime" id="share-end-datetime" type="datetime-local" value="{{ .itemShare.EndDatetime }}"/>
</p>
</div>
</div>
<div class="row">
<div class="col l12">
<p style="margin-right: 6px">
<label for="share-token">Share Url</label>
<div class="input-container">
<span class="prefix">{{ .baseUrl }}/</span>
<input name="Token" id="share-token" type="url" readonly="readonly" value="{{ .itemShare.Token }}" />
</div>
</p>
</div>
</div>
<div class="row">
<div class="col l12">
<p style="margin-right: 6px">
<label for="share-password">Password</label>
<input name="Password" id="share-password" type="password" value=""/>
</p>
</div>
</div>
<div class="row">
<div class="col l6"><p>{{ widget_checkbox "Permission_edit" "Allow editing" "1" "" }}</p></div>
</div>
<div id="footer-navbar">
<button type="submit" class="main" title="Share"><i class='bi bi-floppy'></i><span>Save</span></button>
</div>
</form>
</div>
</dialog>
{{ end }}

View file

@ -19,7 +19,11 @@
<input type="hidden" id="{{$share_name_remove}}" name="{{$share_name_remove}}" value=""/>
</td>
<td class="no-label {{$share_name}}-Col">
{{ .PermissionEdit }}
{{ if eq .PermissionEdit 1}}
<i class="bi bi-check" title="Edit permission granted"></i>
{{ else }}
<i class="bi bi-x" title="Edit permission denied"></i>
{{ end }}
</td>
<td class="no-label {{$share_name}}-Col">
{{ .StartDatetime }}
@ -30,6 +34,7 @@
<td class="no-label">
<button id="Delete-{{$share_name}}" class="delete" type="button" onclick="bm_element_list_delete(this, {{$share_name}}, {{$share_name_remove}})"><i class="bi bi-x-square" title="Remove"></i><span>Remove</span></button>
<button id="Undelete-{{$share_name}}" style="margin-right: 5px;" class="delete" type="button" onclick="bm_element_list_undelete(this, {{$share_name}}, {{$share_name_remove}})" hidden><i class="bi bi-arrow-counterclockwise" title="Undo"></i><span>Undo</span></button>
<button id="Edit-{{$share_name}}" href="#" hx-target="body" hx-swap="beforeend" hx-get="/item/share/edit/{{.Id}}" class="edit" type="button"><i class="bi bi-pencil" title="Edit"></i><span>Edit</span></button>
</td>
</tr>
{{ end }}

View file

@ -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)
}

View file

@ -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")

View file

@ -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}}
}

View file

@ -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()