feat: multi-delete
This commit is contained in:
parent
73e64f096d
commit
51c33543e8
|
|
@ -32,15 +32,11 @@ func (ctx *Context) WishlistDelete(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
target := r.Form.Get("gift_id")
|
||||
if target == "" {
|
||||
http.Error(w, "Gift ID not provided"+target, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
err := user.RemoveGift(target)
|
||||
targets := r.Form["gift"]
|
||||
err := user.RemoveGifts(targets...)
|
||||
if err != nil {
|
||||
log.Printf("Failed to remove gift: %s\n", err)
|
||||
http.Error(w, "Failed to remove gift.", http.StatusInternalServerError)
|
||||
log.Printf("Failed to remove gifts: %s\n", err)
|
||||
http.Error(w, "Failed to remove gifts.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
)
|
||||
|
||||
type HomeProps struct {
|
||||
Username string
|
||||
Gifts []db.Gift
|
||||
Reference string
|
||||
}
|
||||
|
|
@ -19,6 +20,6 @@ func (ctx *Context) Home(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
p := HomeProps{Gifts: gifts, Reference: user.Reference}
|
||||
p := HomeProps{Username: user.Name, Gifts: gifts, Reference: user.Reference}
|
||||
templates.Execute(w, "home.gotmpl", p)
|
||||
}
|
||||
|
|
|
|||
89
db/user.go
89
db/user.go
|
|
@ -120,38 +120,84 @@ func (u *User) AddGift(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *User) RemoveGift(id string) error {
|
||||
func (u *User) deleteGifts(tx *sql.Tx, ids []string) error {
|
||||
stmt := "DELETE FROM gift WHERE gift.creator_id = ? AND gift.id = ?"
|
||||
result, err := database.Exec(stmt, u.Id, id)
|
||||
for _, id := range ids {
|
||||
r, err := tx.Exec(stmt, u.Id, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rE, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rE < 1 {
|
||||
return fmt.Errorf("Gift deletion failed for '%s'", id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) RemoveGifts(ids ...string) error {
|
||||
if len(ids) < 1 {
|
||||
return fmt.Errorf("Attempt to remove zero gifts")
|
||||
}
|
||||
|
||||
tx, err := database.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, _ := result.RowsAffected()
|
||||
if affected == 0 {
|
||||
return fmt.Errorf("No gift match.")
|
||||
|
||||
err = u.deleteGifts(tx, ids)
|
||||
if err != nil {
|
||||
rollBackErr := tx.Rollback()
|
||||
if rollBackErr != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
err = tx.Commit()
|
||||
return err
|
||||
}
|
||||
|
||||
func (u *User) executeClaims(tx *sql.Tx, claims, unclaims []string) error {
|
||||
claimStmt := "UPDATE gift SET claimant_id = ? WHERE id = ?"
|
||||
unclaimStmt := "UPDATE gift SET claimant_id = NULL WHERE id = ?"
|
||||
for _, id := range claims {
|
||||
_, err := tx.Exec(claimStmt, u.Id, id)
|
||||
r, err := tx.Exec(claimStmt, u.Id, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, id := range unclaims {
|
||||
_, err := tx.Exec(unclaimStmt, id)
|
||||
rE, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rE < 1 {
|
||||
return fmt.Errorf("Gift claim failed for '%s'", id)
|
||||
}
|
||||
}
|
||||
for _, id := range unclaims {
|
||||
r, err := tx.Exec(unclaimStmt, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rE, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rE < 1 {
|
||||
return fmt.Errorf("Gift unclaim failed for '%s'", id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) ClaimGifts(claims, unclaims []string) error {
|
||||
if len(claims) < 1 && len(unclaims) < 1 {
|
||||
return fmt.Errorf("Attempt to claim/unclaim zero gifts")
|
||||
}
|
||||
|
||||
tx, err := database.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -159,7 +205,10 @@ func (u *User) ClaimGifts(claims, unclaims []string) error {
|
|||
|
||||
err = u.executeClaims(tx, claims, unclaims)
|
||||
if err != nil {
|
||||
err = tx.Rollback()
|
||||
rollBackErr := tx.Rollback()
|
||||
if rollBackErr != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -170,15 +219,26 @@ func (u *User) ClaimGifts(claims, unclaims []string) error {
|
|||
func (u *User) executeCompletions(tx *sql.Tx, claims []string) error {
|
||||
claimStmt := "UPDATE gift SET sent = 1 WHERE id = ?"
|
||||
for _, id := range claims {
|
||||
_, err := tx.Exec(claimStmt, id)
|
||||
r, err := tx.Exec(claimStmt, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rE, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rE < 1 {
|
||||
return fmt.Errorf("Gift completion failed for '%s'", id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) CompleteGifts(claims []string) error {
|
||||
if len(claims) < 1 {
|
||||
return fmt.Errorf("Attempt to complete zero gifts")
|
||||
}
|
||||
|
||||
tx, err := database.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -186,7 +246,10 @@ func (u *User) CompleteGifts(claims []string) error {
|
|||
|
||||
err = u.executeCompletions(tx, claims)
|
||||
if err != nil {
|
||||
err = tx.Rollback()
|
||||
rollBackErr := tx.Rollback()
|
||||
if rollBackErr != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,18 @@
|
|||
<head>
|
||||
<title>Lishwist</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script>
|
||||
function someChecked(checkList) {
|
||||
if (!checkList) {
|
||||
return
|
||||
}
|
||||
return Array.from(checkList).some(({checked}) => checked);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{template "body" .}}
|
||||
{{template "body" .}}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -8,34 +8,35 @@
|
|||
</ul>
|
||||
</nav>
|
||||
<h2>{{.Username}}'s list</h2>
|
||||
<form method="post" action="/{{.UserReference}}/update" autocomplete="off">
|
||||
<button type="submit" name="mode" value="claim">Claim/Unclaim</button>
|
||||
<button type="submit" name="mode" value="complete">Complete</button>
|
||||
<form method="post" action="/{{.UserReference}}/update" autocomplete="off"
|
||||
onchange="const checked = someChecked(this.unclaimed) || someChecked(this.claimed); this.mode[0].disabled = !checked; this.mode[1].disabled = !checked;">
|
||||
<button type="submit" name="mode" value="claim" disabled>Claim/Unclaim</button>
|
||||
<button type="submit" name="mode" value="complete" disabled>Complete</button>
|
||||
<ul>
|
||||
{{range .Gifts}}
|
||||
<li>
|
||||
<label>
|
||||
{{if .ClaimantId}}
|
||||
{{if .ClaimantId}}
|
||||
{{if eq .ClaimantId $.CurrentUserId}}
|
||||
<input type="checkbox" name="claimed" value="{{.Id}}" {{if .Sent}}disabled{{end}}>
|
||||
<input type="checkbox" name="claimed" value="{{.Id}}" {{if .Sent}}disabled{{end}}>
|
||||
{{else}}
|
||||
<input type="checkbox" disabled>
|
||||
<input type="checkbox" disabled>
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{else}}
|
||||
<input type="checkbox" name="unclaimed" value="{{.Id}}" {{if .Sent}}disabled{{end}}>
|
||||
{{end}}
|
||||
{{if .Sent}}
|
||||
<s>{{.Name}}</s>
|
||||
{{else}}
|
||||
{{.Name}}
|
||||
{{end}}
|
||||
{{if .ClaimantId}}
|
||||
{{if eq .ClaimantId $.CurrentUserId}}
|
||||
<span style="color: blue;">{{if .Sent}}Completed{{else}}Claimed{{end}} by you</span>
|
||||
{{else}}
|
||||
<span style="color: red;">{{if .Sent}}Completed{{else}}Claimed{{end}} by {{.ClaimantName}}</span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .Sent}}
|
||||
<s>{{.Name}}</s>
|
||||
{{else}}
|
||||
{{.Name}}
|
||||
{{end}}
|
||||
{{if .ClaimantId}}
|
||||
{{if eq .ClaimantId $.CurrentUserId}}
|
||||
<span style="color: blue;">{{if .Sent}}Completed{{else}}Claimed{{end}} by you</span>
|
||||
{{else}}
|
||||
<span style="color: red;">{{if .Sent}}Completed{{else}}Claimed{{end}} by {{.ClaimantName}}</span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</label>
|
||||
</li>
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{{define "body"}}
|
||||
<p>Logged in as '{{.Username}}'</p>
|
||||
<form method="post" action="/logout">
|
||||
<input type="submit" value="Logout">
|
||||
</form>
|
||||
|
|
@ -10,16 +11,18 @@
|
|||
</dd>
|
||||
</dl>
|
||||
<h2>Your list</h2>
|
||||
<ul>
|
||||
{{range .Gifts}}
|
||||
<li>{{.Name}}
|
||||
<form method="post" action="wishlist/delete">
|
||||
<input type="hidden" name="gift_id" value="{{.Id}}">
|
||||
<input type="submit" value="Delete">
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
<form method="post" action="/wishlist/delete" onchange="this.mode.disabled = !someChecked(this.gift)"
|
||||
autocomplete="off">
|
||||
<button type="submit" name="mode" value="delete" disabled>Delete</button>
|
||||
<ul>
|
||||
{{range .Gifts}}
|
||||
<li>
|
||||
<input type="checkbox" name="gift" value="{{.Id}}">
|
||||
{{.Name}}
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</form>
|
||||
<form method="post" action="/wishlist/add">
|
||||
<input name="gift_name" required>
|
||||
<input type="submit">
|
||||
|
|
|
|||
Loading…
Reference in New Issue