Compare commits
2 Commits
ffb27bfd93
...
b38e707ae2
| Author | SHA1 | Date |
|---|---|---|
|
|
b38e707ae2 | |
|
|
7d46722053 |
|
|
@ -49,7 +49,7 @@ func (ctx *Context) UpdateForeignWishlist(w http.ResponseWriter, r *http.Request
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userReference := r.PathValue("userReference")
|
userReference := r.PathValue("userReference")
|
||||||
switch r.Form.Get("mode") {
|
switch r.Form.Get("intent") {
|
||||||
case "claim":
|
case "claim":
|
||||||
claims := r.Form["unclaimed"]
|
claims := r.Form["unclaimed"]
|
||||||
unclaims := r.Form["claimed"]
|
unclaims := r.Form["claimed"]
|
||||||
|
|
@ -66,8 +66,30 @@ func (ctx *Context) UpdateForeignWishlist(w http.ResponseWriter, r *http.Request
|
||||||
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
|
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case "add":
|
||||||
|
giftName := r.Form.Get("gift_name")
|
||||||
|
if giftName == "" {
|
||||||
|
http.Error(w, "Gift name not provided", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := user.AddGiftToUser(userReference, giftName)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to add gift idea to other user: %s\n", err)
|
||||||
|
http.Error(w, "Failed to add gift idea to other user...", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "delete":
|
||||||
|
claims := r.Form["unclaimed"]
|
||||||
|
unclaims := r.Form["claimed"]
|
||||||
|
gifts := append(claims, unclaims...)
|
||||||
|
err := user.RemoveGifts(gifts...)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to remove gift idea for other user: %s\n", err)
|
||||||
|
http.Error(w, "Failed to remove gift idea for other user...", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
http.Error(w, "Invalid mode", http.StatusBadRequest)
|
http.Error(w, "Invalid intent", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
|
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ func (ctx *Context) ViewForeignWishlist(w http.ResponseWriter, r *http.Request)
|
||||||
http.Error(w, "User not found", http.StatusNotFound)
|
http.Error(w, "User not found", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gifts, err := otherUser.GetGifts()
|
gifts, err := user.GetOtherUserGifts(userReference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("An error occurred while fetching %s's wishlist: %s\n", otherUser.Name, err)
|
log.Printf("An error occurred while fetching %s's wishlist: %s\n", otherUser.Name, err)
|
||||||
http.Error(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError)
|
http.Error(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError)
|
||||||
|
|
|
||||||
78
db/user.go
78
db/user.go
|
|
@ -19,8 +19,11 @@ type Gift struct {
|
||||||
ClaimantId string
|
ClaimantId string
|
||||||
ClaimantName string
|
ClaimantName string
|
||||||
Sent bool
|
Sent bool
|
||||||
|
RecipientId string
|
||||||
RecipientName string
|
RecipientName string
|
||||||
RecipientRef string
|
RecipientRef string
|
||||||
|
CreatorId string
|
||||||
|
CreatorName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryForUser(query string, args ...any) (*User, error) {
|
func queryForUser(query string, args ...any) (*User, error) {
|
||||||
|
|
@ -83,7 +86,7 @@ func (u *User) GetPassHash() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) GetGifts() ([]Gift, error) {
|
func (u *User) GetGifts() ([]Gift, error) {
|
||||||
stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE user.id = ?"
|
stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE gift.creator_id = user.id AND user.id = ?"
|
||||||
rows, err := database.Query(stmt, u.Id)
|
rows, err := database.Query(stmt, u.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -93,15 +96,18 @@ func (u *User) GetGifts() ([]Gift, error) {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var id string
|
var id string
|
||||||
var name string
|
var name string
|
||||||
var claimantId string
|
var claimantId sql.NullString
|
||||||
var claimantName string
|
var claimantName sql.NullString
|
||||||
var sent bool
|
var sent bool
|
||||||
rows.Scan(&id, &name, &claimantId, &claimantName, &sent)
|
err = rows.Scan(&id, &name, &claimantId, &claimantName, &sent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
gift := Gift{
|
gift := Gift{
|
||||||
Id: id,
|
Id: id,
|
||||||
Name: name,
|
Name: name,
|
||||||
ClaimantId: claimantId,
|
ClaimantId: claimantId.String,
|
||||||
ClaimantName: claimantName,
|
ClaimantName: claimantName.String,
|
||||||
Sent: sent,
|
Sent: sent,
|
||||||
}
|
}
|
||||||
gifts = append(gifts, gift)
|
gifts = append(gifts, gift)
|
||||||
|
|
@ -113,6 +119,53 @@ func (u *User) GetGifts() ([]Gift, error) {
|
||||||
return gifts, nil
|
return gifts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) GetOtherUserGifts(otherUserReference string) ([]Gift, error) {
|
||||||
|
otherUser, err := GetUserByReference(otherUserReference)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if otherUser.Id == u.Id {
|
||||||
|
return nil, fmt.Errorf("Not allowed to view own foreign wishlist")
|
||||||
|
}
|
||||||
|
stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent, gift.creator_id, creator.name, gift.recipient_id FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id LEFT JOIN user AS creator ON gift.creator_id = creator.id WHERE user.id = ?"
|
||||||
|
rows, err := database.Query(stmt, otherUser.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
gifts := []Gift{}
|
||||||
|
for rows.Next() {
|
||||||
|
var id string
|
||||||
|
var name string
|
||||||
|
var claimantId sql.NullString
|
||||||
|
var claimantName sql.NullString
|
||||||
|
var sent bool
|
||||||
|
var creatorId string
|
||||||
|
var creatorName string
|
||||||
|
var recipientId string
|
||||||
|
err = rows.Scan(&id, &name, &claimantId, &claimantName, &sent, &creatorId, &creatorName, &recipientId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gift := Gift{
|
||||||
|
Id: id,
|
||||||
|
Name: name,
|
||||||
|
ClaimantId: claimantId.String,
|
||||||
|
ClaimantName: claimantName.String,
|
||||||
|
Sent: sent,
|
||||||
|
CreatorId: creatorId,
|
||||||
|
CreatorName: creatorName,
|
||||||
|
RecipientId: recipientId,
|
||||||
|
}
|
||||||
|
gifts = append(gifts, gift)
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return gifts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) GetTodo() ([]Gift, error) {
|
func (u *User) GetTodo() ([]Gift, error) {
|
||||||
stmt := "SELECT gift.id, gift.name, gift.sent, recipient.name, recipient.reference FROM gift JOIN user ON gift.claimant_id = user.id JOIN user AS recipient ON gift.recipient_id = recipient.id WHERE user.id = ? ORDER BY gift.sent ASC, gift.name"
|
stmt := "SELECT gift.id, gift.name, gift.sent, recipient.name, recipient.reference FROM gift JOIN user ON gift.claimant_id = user.id JOIN user AS recipient ON gift.recipient_id = recipient.id WHERE user.id = ? ORDER BY gift.sent ASC, gift.name"
|
||||||
rows, err := database.Query(stmt, u.Id)
|
rows, err := database.Query(stmt, u.Id)
|
||||||
|
|
@ -289,3 +342,16 @@ func (u *User) CompleteGifts(claims []string) error {
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) AddGiftToUser(otherUserReference string, giftName string) error {
|
||||||
|
otherUser, err := GetUserByReference(otherUserReference)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stmt := "INSERT INTO gift (name, recipient_id, creator_id) VALUES (?, ?, ?)"
|
||||||
|
_, err = database.Exec(stmt, giftName, otherUser.Id, u.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@
|
||||||
const accepted = submissionNames.length > 0 && submissionNames.every((name) => acceptedNames.includes(name));
|
const accepted = submissionNames.length > 0 && submissionNames.every((name) => acceptedNames.includes(name));
|
||||||
submitter.disabled = !accepted;
|
submitter.disabled = !accepted;
|
||||||
}
|
}
|
||||||
|
function acceptAttribute(form, submitId, acceptedAttribute) {
|
||||||
|
const checkedInputs = Array.from(form.querySelectorAll("input")).filter((i) => i.checked);
|
||||||
|
const submitter = document.getElementById(submitId);
|
||||||
|
const accepted = checkedInputs.length > 0 && checkedInputs.every((i) => i.hasAttribute(acceptedAttribute));
|
||||||
|
submitter.disabled = !accepted;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,49 +33,63 @@
|
||||||
<h2>{{.Username}}'s list</h2>
|
<h2>{{.Username}}'s list</h2>
|
||||||
{{with .Gifts}}
|
{{with .Gifts}}
|
||||||
<form method="post" action="/{{$.UserReference}}/update" autocomplete="off"
|
<form method="post" action="/{{$.UserReference}}/update" autocomplete="off"
|
||||||
onchange="acceptNames(this, 'claimSubmit', 'claimed', 'unclaimed'); acceptNames(this, 'completeSubmit', 'claimed');">
|
onchange="acceptNames(this, 'claimSubmit', 'claimed', 'unclaimed'); acceptNames(this, 'completeSubmit', 'claimed'); acceptAttribute(this, 'deleteSubmit', 'data-deletable')">
|
||||||
<button id="claimSubmit" class="btn btn-warning" type="submit" name="mode" value="claim"
|
<ul class="list-group mb-3">
|
||||||
disabled>Claim/Unclaim</button>
|
|
||||||
<button id="completeSubmit" class="btn btn-success" type="submit" name="mode" value="complete"
|
|
||||||
disabled>Complete</button>
|
|
||||||
<ul class="list-group mt-3">
|
|
||||||
{{range .}}
|
{{range .}}
|
||||||
|
{{$isMine := eq .ClaimantId $.CurrentUserId}}
|
||||||
|
{{$createdByMe := eq .CreatorId $.CurrentUserId}}
|
||||||
|
{{$outsideIdea := ne .RecipientId .CreatorId}}
|
||||||
<li class="list-group-item{{if .Sent}} list-group-item-light{{end}}">
|
<li class="list-group-item{{if .Sent}} list-group-item-light{{end}}">
|
||||||
{{if .ClaimantId}}
|
|
||||||
{{if eq .ClaimantId $.CurrentUserId}}
|
|
||||||
<input id="foreignlist_select_{{.Id}}" class="form-check-input" type="checkbox"
|
<input id="foreignlist_select_{{.Id}}" class="form-check-input" type="checkbox"
|
||||||
aria-describedby="wish_detail_{{.Id}}" name="claimed" value="{{.Id}}" {{if .Sent}}disabled{{end}}>
|
aria-describedby="wish_detail_{{.Id}}" {{if $isMine}} name="claimed" value="{{.Id}}" {{else if
|
||||||
{{else}}
|
.ClaimantId}} disabled {{else}} name="unclaimed" value="{{.Id}}" {{end}} {{if .Sent}} disabled {{end}}
|
||||||
<input id="foreignlist_select_{{.Id}}" class="form-check-input" type="checkbox"
|
{{if $createdByMe}}data-deletable{{end}}>
|
||||||
aria-describedby="wish_detail_{{.Id}}" disabled>
|
|
||||||
{{end}}
|
<label class="form-check-label stretched-link" for="foreignlist_select_{{.Id}}">
|
||||||
{{else}}
|
|
||||||
<input id="foreignlist_select_{{.Id}}" class="form-check-input" type="checkbox"
|
|
||||||
aria-describedby="wish_detail_{{.Id}}" name="unclaimed" value="{{.Id}}" {{if .Sent}}disabled{{end}}>
|
|
||||||
{{end}}
|
|
||||||
<label class="form-check-label" for="foreignlist_select_{{.Id}}">
|
|
||||||
{{if .Sent}}
|
{{if .Sent}}
|
||||||
<s>{{.Name}}</s>
|
<s>{{.Name}}</s>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{.Name}}
|
{{.Name}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</label>
|
</label>
|
||||||
{{if .ClaimantId}}
|
|
||||||
{{if eq .ClaimantId $.CurrentUserId}}
|
{{if or .ClaimantId $outsideIdea}}
|
||||||
<span id="wish_detail_{{.Id}}" style="color: blue;">{{if .Sent}}Completed{{else}}Claimed{{end}} by
|
<div class="d-inline" id="wish_detail_{{.Id}}">
|
||||||
you</span>
|
{{if .ClaimantId}}
|
||||||
{{else}}
|
<span style="color: {{if $isMine}}blue{{else}}red{{end}};">{{if .Sent}}Completed{{else}}Claimed{{end}}
|
||||||
<span id="wish_detail_{{.Id}}" style="color: red;">{{if .Sent}}Completed{{else}}Claimed{{end}} by
|
by
|
||||||
{{.ClaimantName}}</span>
|
{{if $isMine}}<em>you</em>{{else}}{{.ClaimantName}}{{end}}</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{if $outsideIdea}}
|
||||||
|
<span style="color: green;">Added by {{if
|
||||||
|
$createdByMe}}<em>you</em>{{else}}{{.CreatorName}}{{end}}</span>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
|
<button id="claimSubmit" class="btn btn-warning" type="submit" name="intent" value="claim"
|
||||||
|
disabled>Claim/Unclaim</button>
|
||||||
|
<button id="completeSubmit" class="btn btn-success" type="submit" name="intent" value="complete"
|
||||||
|
disabled>Complete</button>
|
||||||
|
<button id="deleteSubmit" class="btn btn-danger" type="submit" name="intent" value="delete"
|
||||||
|
disabled>Delete</button>
|
||||||
</form>
|
</form>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>They haven't wished for anything. Ask them to think of some stuff!</p>
|
<p>They don't have any gift ideas. Ask them to think of something, or add an idea yourself! 👇 (everyone
|
||||||
|
except them will be able to see it and claim it)</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<form method="post" action="/{{$.UserReference}}/update">
|
||||||
|
<div class="input-group mt-3">
|
||||||
|
<input class="form-control" name="gift_name"
|
||||||
|
placeholder="This will be invisible to {{.Username}}, but everyone else will be able to see it and possibly claim it."
|
||||||
|
required>
|
||||||
|
<button class="btn btn-primary" type="submit" name="intent" value="add">Add gift idea</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,6 @@
|
||||||
{{with .Gifts}}
|
{{with .Gifts}}
|
||||||
<form method="post" action="/wishlist/delete" onchange="acceptNames(this, 'deleteSubmit', 'gift')"
|
<form method="post" action="/wishlist/delete" onchange="acceptNames(this, 'deleteSubmit', 'gift')"
|
||||||
autocomplete="off">
|
autocomplete="off">
|
||||||
<button id="deleteSubmit" class="btn btn-danger mb-3" type="submit" name="mode" value="delete"
|
|
||||||
disabled>Delete</button>
|
|
||||||
<ul class="list-group mb-3">
|
<ul class="list-group mb-3">
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
|
|
@ -42,6 +40,8 @@
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
|
<button id="deleteSubmit" class="btn btn-danger mb-3" type="submit" name="mode" value="delete"
|
||||||
|
disabled>Delete</button>
|
||||||
</form>
|
</form>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>Your list is empty. Think of some things to add!</p>
|
<p>Your list is empty. Think of some things to add!</p>
|
||||||
|
|
@ -62,11 +62,7 @@
|
||||||
<form method="post" action="/todo/update"
|
<form method="post" action="/todo/update"
|
||||||
onchange="acceptNames(this, 'unclaimSubmit', 'gift'); acceptNames(this, 'completeSubmit', 'gift')"
|
onchange="acceptNames(this, 'unclaimSubmit', 'gift'); acceptNames(this, 'completeSubmit', 'gift')"
|
||||||
autocomplete="off">
|
autocomplete="off">
|
||||||
<button id="unclaimSubmit" class="btn btn-warning" type="submit" name="mode" value="unclaim"
|
<ul class="list-group mb-3">
|
||||||
disabled>Unclaim</button>
|
|
||||||
<button id="completeSubmit" class="btn btn-success" type="submit" name="mode" value="complete"
|
|
||||||
disabled>Complete</button>
|
|
||||||
<ul class="list-group mt-3">
|
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<li class="list-group-item{{if .Sent}} list-group-item-light{{end}}">
|
<li class="list-group-item{{if .Sent}} list-group-item-light{{end}}">
|
||||||
<input id="todo_select_{{.Id}}" class="form-check-input" type="checkbox" {{if .Sent}}
|
<input id="todo_select_{{.Id}}" class="form-check-input" type="checkbox" {{if .Sent}}
|
||||||
|
|
@ -86,10 +82,14 @@
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
|
<button id="unclaimSubmit" class="btn btn-warning" type="submit" name="mode" value="unclaim"
|
||||||
|
disabled>Unclaim</button>
|
||||||
|
<button id="completeSubmit" class="btn btn-success" type="submit" name="mode" value="complete"
|
||||||
|
disabled>Complete</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
Loading…
Reference in New Issue