RSVP 0.13.0 and fix templates
This commit is contained in:
parent
dfa2525714
commit
c763ff40d4
|
|
@ -5,7 +5,7 @@ go 1.23.3
|
|||
toolchain go1.24.5
|
||||
|
||||
require (
|
||||
github.com/Teajey/rsvp v0.11.0
|
||||
github.com/Teajey/rsvp v0.13.0
|
||||
github.com/Teajey/sqlstore v0.0.6
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
golang.org/x/crypto v0.22.0
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
github.com/Teajey/rsvp v0.11.0 h1:ePx7Oj0nDYRCmFB6fQvSQbYUcWhgqTh9fh8PaHlOnwk=
|
||||
github.com/Teajey/rsvp v0.11.0/go.mod h1:WCWos0l+K/9heUuvbIUXkKAHAtxoLpkJ43C/fszD4RY=
|
||||
github.com/Teajey/rsvp v0.13.0 h1:EeuHMHtU2/eLuSbCIlzKqy5FI9f6Qq+yUJnrVPBJvKk=
|
||||
github.com/Teajey/rsvp v0.13.0/go.mod h1:WCWos0l+K/9heUuvbIUXkKAHAtxoLpkJ43C/fszD4RY=
|
||||
github.com/Teajey/sqlstore v0.0.6 h1:kUEpA+3BKFHZl128MuMeYY6zVcmq1QmOlNyofcFEJOA=
|
||||
github.com/Teajey/sqlstore v0.0.6/go.mod h1:hjk0S593/2Q4QxkEXCgpThj9w5KWGTQi9JtgfziHXXk=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"lishwist/http/templates"
|
||||
"log"
|
||||
"net/http"
|
||||
|
|
@ -17,7 +16,7 @@ type ServeMux struct {
|
|||
|
||||
func NewServeMux(store *sqlstore.Store) *ServeMux {
|
||||
mux := rsvp.NewServeMux()
|
||||
mux.Config.HtmlTemplate = templates.Templates["login.gotmpl"]
|
||||
mux.Config.HtmlTemplate = templates.Template
|
||||
return &ServeMux{
|
||||
inner: mux,
|
||||
store: store,
|
||||
|
|
@ -35,7 +34,7 @@ type Handler interface {
|
|||
type HandlerFunc func(*Session, http.Header, *http.Request) rsvp.Response
|
||||
|
||||
func (m *ServeMux) HandleFunc(pattern string, handler HandlerFunc) {
|
||||
m.inner.Std.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
|
||||
m.inner.MiddleHandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) rsvp.Response {
|
||||
session := m.GetSession(r)
|
||||
|
||||
response := handler(session, w.Header(), r)
|
||||
|
|
@ -47,10 +46,7 @@ func (m *ServeMux) HandleFunc(pattern string, handler HandlerFunc) {
|
|||
}
|
||||
}
|
||||
|
||||
err := response.Write(w, r, m.inner.Config)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to write rsvp.Response: %s", err))
|
||||
}
|
||||
return response
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ type Session struct {
|
|||
|
||||
func (s *Session) FlashGet() any {
|
||||
list := s.inner.Flashes()
|
||||
s.written = true
|
||||
if len(list) < 1 {
|
||||
return nil
|
||||
} else {
|
||||
s.written = true
|
||||
return list[0]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type foreignWishlistProps struct {
|
|||
func ForeignWishlist(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
|
||||
userReference := r.PathValue("userReference")
|
||||
if app.User.Reference == userReference {
|
||||
return rsvp.SeeOther("/")
|
||||
return rsvp.Found("/", "You're not allowed to view your own wishlist!")
|
||||
}
|
||||
otherUser, err := lishwist.GetUserByReference(userReference)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -44,12 +44,14 @@ func LoginPost(session *response.Session, h http.Header, r *http.Request) rsvp.R
|
|||
|
||||
props := api.NewLoginProps(username, password)
|
||||
|
||||
resp := rsvp.SeeOther(r.URL.Path, props)
|
||||
|
||||
valid := props.Validate()
|
||||
props.Password.Value = ""
|
||||
if !valid {
|
||||
session.FlashSet(&props)
|
||||
log.Printf("Invalid props: %#v\n", props)
|
||||
return rsvp.SeeOther("/")
|
||||
return resp
|
||||
}
|
||||
|
||||
app, err := lishwist.Login(username, password)
|
||||
|
|
@ -59,12 +61,12 @@ func LoginPost(session *response.Session, h http.Header, r *http.Request) rsvp.R
|
|||
props.GeneralError = "Username or password invalid"
|
||||
session.FlashSet(&props)
|
||||
log.Printf("Invalid credentials: %s: %#v\n", err, props)
|
||||
return rsvp.SeeOther("/")
|
||||
return resp
|
||||
default:
|
||||
props.GeneralError = "Something went wrong."
|
||||
session.FlashSet(&props)
|
||||
log.Printf("Login error: %s\n", err)
|
||||
return rsvp.SeeOther("/")
|
||||
return resp
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,5 +74,5 @@ func LoginPost(session *response.Session, h http.Header, r *http.Request) rsvp.R
|
|||
session.SetValue("authorized", true)
|
||||
session.SetValue("username", app.User.Name)
|
||||
|
||||
return rsvp.SeeOther(r.URL.Path)
|
||||
return rsvp.SeeOther(r.URL.Path, "Login successful!")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ func LogoutPost(session *response.Session, h http.Header, r *http.Request) rsvp.
|
|||
session.Options().MaxAge = 0
|
||||
session.ClearValues()
|
||||
|
||||
return rsvp.SeeOther("/")
|
||||
return rsvp.SeeOther("/", "Logout successful")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ func RegisterPost(s *response.Session, h http.Header, r *http.Request) rsvp.Resp
|
|||
props.ConfirmPassword.Value = ""
|
||||
if !valid {
|
||||
s.FlashSet(&props)
|
||||
log.Printf("Invalid props: %#v\n", props)
|
||||
return rsvp.SeeOther("/")
|
||||
log.Printf("Invalid register props: %#v\n", props)
|
||||
return rsvp.SeeOther(r.URL.Path, props)
|
||||
}
|
||||
|
||||
_, err = lishwist.Register(username, newPassword)
|
||||
|
|
@ -58,9 +58,9 @@ func RegisterPost(s *response.Session, h http.Header, r *http.Request) rsvp.Resp
|
|||
}
|
||||
s.FlashSet(&props)
|
||||
log.Printf("Registration failed: %s\n", err)
|
||||
return rsvp.SeeOther("/register")
|
||||
return rsvp.SeeOther(r.URL.Path, props)
|
||||
}
|
||||
|
||||
s.FlashSet(true)
|
||||
return rsvp.SeeOther("/")
|
||||
return rsvp.SeeOther("/", "Registration successful!")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ func TodoUpdate(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Resp
|
|||
default:
|
||||
return response.Error(http.StatusBadRequest, "Invalid intent")
|
||||
}
|
||||
return rsvp.SeeOther("/")
|
||||
return rsvp.SeeOther("/", "Update successful")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ func WishlistAdd(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Res
|
|||
log.Printf("%s\n", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to add gift.")
|
||||
}
|
||||
return rsvp.SeeOther("/")
|
||||
return rsvp.SeeOther("/", "Wish added!")
|
||||
}
|
||||
|
||||
func WishlistDelete(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
|
||||
|
|
@ -37,7 +37,7 @@ func WishlistDelete(app *lishwist.Session, h http.Header, r *http.Request) rsvp.
|
|||
log.Printf("%s\n", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to remove gifts.")
|
||||
}
|
||||
return rsvp.SeeOther("/")
|
||||
return rsvp.SeeOther("/", "Wish deleted")
|
||||
}
|
||||
|
||||
func ForeignWishlistPost(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
|
||||
|
|
@ -47,6 +47,7 @@ func ForeignWishlistPost(app *lishwist.Session, h http.Header, r *http.Request)
|
|||
}
|
||||
|
||||
userReference := r.PathValue("userReference")
|
||||
resp := rsvp.SeeOther("/list/"+userReference, "Update successful")
|
||||
intent := r.Form.Get("intent")
|
||||
switch intent {
|
||||
case "claim":
|
||||
|
|
@ -57,6 +58,7 @@ func ForeignWishlistPost(app *lishwist.Session, h http.Header, r *http.Request)
|
|||
log.Printf("%s\n", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to update claim...")
|
||||
}
|
||||
resp.Body = "Successfully claimed wishes"
|
||||
case "complete":
|
||||
claims := r.Form["claimed"]
|
||||
err := app.CompleteWishes(claims)
|
||||
|
|
@ -64,6 +66,7 @@ func ForeignWishlistPost(app *lishwist.Session, h http.Header, r *http.Request)
|
|||
log.Printf("%s\n", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to complete gifts...")
|
||||
}
|
||||
resp.Body = "Successfully completed wishes"
|
||||
case "add":
|
||||
wishName := r.Form.Get("gift_name")
|
||||
if wishName == "" {
|
||||
|
|
@ -74,6 +77,7 @@ func ForeignWishlistPost(app *lishwist.Session, h http.Header, r *http.Request)
|
|||
log.Printf("%s\n", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to add gift idea to other user...")
|
||||
}
|
||||
resp.Body = "Successfully added wishes"
|
||||
case "delete":
|
||||
claims := r.Form["unclaimed"]
|
||||
unclaims := r.Form["claimed"]
|
||||
|
|
@ -83,8 +87,9 @@ func ForeignWishlistPost(app *lishwist.Session, h http.Header, r *http.Request)
|
|||
log.Printf("%s\n", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to remove gift idea for other user...")
|
||||
}
|
||||
resp.Body = "Successfully removed wishes"
|
||||
default:
|
||||
return response.Error(http.StatusBadRequest, "Invalid intent %q", intent)
|
||||
}
|
||||
return rsvp.SeeOther("/list/" + userReference)
|
||||
return resp
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@
|
|||
{{end}}
|
||||
{{end}}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
{{define "head"}}
|
||||
<title>Lishwist</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
|
|
@ -42,6 +39,11 @@
|
|||
submitter.disabled = !accepted;
|
||||
}
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
{{define "boilerplate"}}
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
@ -61,5 +63,8 @@
|
|||
{{template "body" .}}
|
||||
</div>
|
||||
</body>
|
||||
{{end}}
|
||||
|
||||
</html>
|
||||
{{define "login_prompt"}}
|
||||
<a href="/">Login</a> or <a href="/register">register</a>
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,34 @@
|
|||
{{define "navbar"}}
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "body"}}
|
||||
<div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p class="mb-0">{{.Message}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p class="mb-0">{{.Message}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,98 +1,115 @@
|
|||
{{define "navbar"}}
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="flex-grow-1"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Logged in as '{{.CurrentUserName}}'
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<form class="d-contents" method="post" action="/logout">
|
||||
<button class="dropdown-item" type="submit">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "body"}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2>{{.Username}}'s list</h2>
|
||||
{{with .Gifts}}
|
||||
<form method="post" autocomplete="off"
|
||||
onchange="acceptNames(this, 'claimSubmit', 'claimed', 'unclaimed'); acceptNames(this, 'completeSubmit', 'claimed'); acceptAttribute(this, 'deleteSubmit', 'data-deletable')">
|
||||
<ul class="list-group mb-3">
|
||||
{{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}}">
|
||||
|
||||
<input id="foreignlist_select_{{.Id}}" class="form-check-input" type="checkbox"
|
||||
aria-describedby="wish_detail_{{.Id}}" {{if $isMine}} name="claimed" value="{{.Id}}" {{else if
|
||||
.ClaimantId}} disabled {{else}} name="unclaimed" value="{{.Id}}" {{end}} {{if .Sent}} disabled {{end}}
|
||||
{{if $createdByMe}}data-deletable{{end}}>
|
||||
|
||||
<label class="form-check-label stretched-link" for="foreignlist_select_{{.Id}}">
|
||||
{{if .Sent}}
|
||||
<s>{{.Name}}</s>
|
||||
{{else}}
|
||||
{{.Name}}
|
||||
{{end}}
|
||||
</label>
|
||||
|
||||
{{if or .ClaimantId $outsideIdea}}
|
||||
<div class="d-inline" id="wish_detail_{{.Id}}">
|
||||
{{if .ClaimantId}}
|
||||
<span style="color: {{if $isMine}}blue{{else}}red{{end}};">{{if .Sent}}Completed{{else}}Claimed{{end}}
|
||||
by
|
||||
{{if $isMine}}<em>you</em>{{else}}{{.ClaimantName}}{{end}}</span>
|
||||
{{end}}
|
||||
|
||||
{{if $outsideIdea}}
|
||||
<span style="color: green;">Added by {{if
|
||||
$createdByMe}}<em>you</em>{{else}}{{.CreatorName}}{{end}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</li>
|
||||
{{end}}
|
||||
</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>
|
||||
{{else}}
|
||||
<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}}
|
||||
<form method="post">
|
||||
<div class="input-group mt-3">
|
||||
<input class="form-control" name="gift_name" required aria-describedby="gift_name_help" placeholder="Write a gift idea here" autofocus>
|
||||
<button class="btn btn-primary" type="submit" name="intent" value="add">Add gift idea</button>
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="flex-grow-1"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Logged in as '{{.CurrentUserName}}'
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<form class="d-contents" method="post" action="/logout">
|
||||
<button class="dropdown-item" type="submit">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="gift_name_help" class="form-text">This will be invisible to {{.Username}}, but everyone else will be
|
||||
able to see it and
|
||||
possibly claim it.</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2>{{.Username}}'s list</h2>
|
||||
{{with .Gifts}}
|
||||
<form method="post" autocomplete="off"
|
||||
onchange="acceptNames(this, 'claimSubmit', 'claimed', 'unclaimed'); acceptNames(this, 'completeSubmit', 'claimed'); acceptAttribute(this, 'deleteSubmit', 'data-deletable')">
|
||||
<ul class="list-group mb-3">
|
||||
{{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}}">
|
||||
|
||||
<input id="foreignlist_select_{{.Id}}" class="form-check-input" type="checkbox"
|
||||
aria-describedby="wish_detail_{{.Id}}" {{if $isMine}} name="claimed" value="{{.Id}}" {{else if
|
||||
.ClaimantId}} disabled {{else}} name="unclaimed" value="{{.Id}}" {{end}} {{if .Sent}} disabled {{end}}
|
||||
{{if $createdByMe}}data-deletable{{end}}>
|
||||
|
||||
<label class="form-check-label stretched-link" for="foreignlist_select_{{.Id}}">
|
||||
{{if .Sent}}
|
||||
<s>{{.Name}}</s>
|
||||
{{else}}
|
||||
{{.Name}}
|
||||
{{end}}
|
||||
</label>
|
||||
|
||||
{{if or .ClaimantId $outsideIdea}}
|
||||
<div class="d-inline" id="wish_detail_{{.Id}}">
|
||||
{{if .ClaimantId}}
|
||||
<span style="color: {{if $isMine}}blue{{else}}red{{end}};">{{if .Sent}}Completed{{else}}Claimed{{end}}
|
||||
by
|
||||
{{if $isMine}}<em>you</em>{{else}}{{.ClaimantName}}{{end}}</span>
|
||||
{{end}}
|
||||
|
||||
{{if $outsideIdea}}
|
||||
<span style="color: green;">Added by {{if
|
||||
$createdByMe}}<em>you</em>{{else}}{{.CreatorName}}{{end}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</li>
|
||||
{{end}}
|
||||
</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>
|
||||
{{else}}
|
||||
<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}}
|
||||
<form method="post">
|
||||
<div class="input-group mt-3">
|
||||
<input class="form-control" name="gift_name" required aria-describedby="gift_name_help" placeholder="Write a gift idea here" autofocus>
|
||||
<button class="btn btn-primary" type="submit" name="intent" value="add">Add gift idea</button>
|
||||
</div>
|
||||
<div id="gift_name_help" class="form-text">This will be invisible to {{.Username}}, but everyone else will be
|
||||
able to see it and
|
||||
possibly claim it.</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,50 +1,66 @@
|
|||
{{define "navbar"}}
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="flex-grow-1"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Logged in as '{{.CurrentUsername}}'
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<form class="d-contents" method="post" action="/logout">
|
||||
<button class="dropdown-item" type="submit">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "body"}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2><em>{{.Group.Name}}</em> group members</h2>
|
||||
{{with .Group.Members}}
|
||||
<ul class="list-group">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
<a href="/list/{{.Reference}}">{{.Name}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>There's nobody else in this group.</p>
|
||||
{{end}}
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="flex-grow-1"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Logged in as '{{.CurrentUsername}}'
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<form class="d-contents" method="post" action="/logout">
|
||||
<button class="dropdown-item" type="submit">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2><em>{{.Group.Name}}</em> group members</h2>
|
||||
{{with .Group.Members}}
|
||||
<ul class="list-group">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
<a href="/list/{{.Reference}}">{{.Name}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>There's nobody else in this group.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,113 +1,130 @@
|
|||
{{define "navbar"}}
|
||||
<div class="flex-grow-1"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item"><button class="btn btn-success"
|
||||
onclick="navigator.clipboard.writeText('{{.HostUrl}}/list/{{.Reference}}'); alert('The share link to your wishlist has been copied to your clipboard. Anyone with the link will be able to claim gifts for you. Share it with someone!');">Copy
|
||||
share link</button></li>
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Logged in as '{{.Username}}'
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<form class="d-contents" method="post" action="/logout">
|
||||
<button class="dropdown-item" type="submit">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "body"}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h2>Your wishlist</h2>
|
||||
{{with .Gifts}}
|
||||
<form method="post" onchange="acceptNames(this, 'deleteSubmit', 'gift')" autocomplete="off">
|
||||
<ul class="list-group mb-3">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
<input id="wishlist_select_{{.Id}}" class="form-check-input" type="checkbox" name="gift" value="{{.Id}}">
|
||||
<label class="form-check-label stretched-link" for="wishlist_select_{{.Id}}">
|
||||
{{.Name}}
|
||||
</label>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
<button id="deleteSubmit" class="btn btn-danger mb-3" type="submit" name="intent" value="delete_idea"
|
||||
disabled>Delete</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<p>Your list is empty. Think of some things to add!</p>
|
||||
{{end}}
|
||||
<form method="post">
|
||||
<div class="input-group">
|
||||
<input class="form-control" name="gift_name" required placeholder="Write a gift idea here" autofocus>
|
||||
<button class="btn btn-primary" type="submit" name="intent" value="add_idea">Add gift idea</button>
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<div class="flex-grow-1"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item"><button class="btn btn-success"
|
||||
onclick="navigator.clipboard.writeText('{{.HostUrl}}/list/{{.Reference}}'); alert('The share link to your wishlist has been copied to your clipboard. Anyone with the link will be able to claim gifts for you. Share it with someone!');">Copy
|
||||
share link</button></li>
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Logged in as '{{.Username}}'
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<form class="d-contents" method="post" action="/logout">
|
||||
<button class="dropdown-item" type="submit">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h2>Your todo list</h2>
|
||||
{{with .Todo}}
|
||||
<form method="post"
|
||||
onchange="acceptNames(this, 'unclaimSubmit', 'gift'); acceptNames(this, 'completeSubmit', 'gift')"
|
||||
autocomplete="off">
|
||||
<ul class="list-group mb-3">
|
||||
{{range .}}
|
||||
<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}}
|
||||
aria-describedby="todo_detail_{{.Id}}" disabled{{else}} name="gift" value="{{.Id}}" {{end}}>
|
||||
<label for="todo_select_{{.Id}}" class="form-check-label">
|
||||
<em>
|
||||
{{if .Sent}}
|
||||
<s>{{.Name}}</s>
|
||||
{{else}}
|
||||
{{.Name}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h2>Your wishlist</h2>
|
||||
{{with .Gifts}}
|
||||
<form method="post" onchange="acceptNames(this, 'deleteSubmit', 'gift')" autocomplete="off">
|
||||
<ul class="list-group mb-3">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
<input id="wishlist_select_{{.Id}}" class="form-check-input" type="checkbox" name="gift" value="{{.Id}}">
|
||||
<label class="form-check-label stretched-link" for="wishlist_select_{{.Id}}">
|
||||
{{.Name}}
|
||||
</label>
|
||||
</li>
|
||||
{{end}}
|
||||
</em>
|
||||
</label>
|
||||
<span id="todo_detail_{{.Id}}">
|
||||
for <a href="/list/{{.RecipientRef}}">{{.RecipientName}}</a>
|
||||
</span>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
<button id="unclaimSubmit" class="btn btn-warning" type="submit" name="intent" value="unclaim_todo"
|
||||
disabled>Unclaim</button>
|
||||
<button id="completeSubmit" class="btn btn-success" type="submit" name="intent" value="complete_todo"
|
||||
disabled>Complete</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<p class="mb-0">When you claim gifts for others, they will appear here.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</ul>
|
||||
<button id="deleteSubmit" class="btn btn-danger mb-3" type="submit" name="intent" value="delete_idea"
|
||||
disabled>Delete</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<p>Your list is empty. Think of some things to add!</p>
|
||||
{{end}}
|
||||
<form method="post">
|
||||
<div class="input-group">
|
||||
<input class="form-control" name="gift_name" required placeholder="Write a gift idea here" autofocus>
|
||||
<button class="btn btn-primary" type="submit" name="intent" value="add_idea">Add gift idea</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2>Your groups</h2>
|
||||
{{with .Groups}}
|
||||
<ul class="list-group">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
<a href="/groups/{{.Reference}}">{{.Name}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>You don't belong to any groups</p>
|
||||
{{end}}
|
||||
<section class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h2>Your todo list</h2>
|
||||
{{with .Todo}}
|
||||
<form method="post"
|
||||
onchange="acceptNames(this, 'unclaimSubmit', 'gift'); acceptNames(this, 'completeSubmit', 'gift')"
|
||||
autocomplete="off">
|
||||
<ul class="list-group mb-3">
|
||||
{{range .}}
|
||||
<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}}
|
||||
aria-describedby="todo_detail_{{.Id}}" disabled{{else}} name="gift" value="{{.Id}}" {{end}}>
|
||||
<label for="todo_select_{{.Id}}" class="form-check-label">
|
||||
<em>
|
||||
{{if .Sent}}
|
||||
<s>{{.Name}}</s>
|
||||
{{else}}
|
||||
{{.Name}}
|
||||
{{end}}
|
||||
</em>
|
||||
</label>
|
||||
<span id="todo_detail_{{.Id}}">
|
||||
for <a href="/list/{{.RecipientRef}}">{{.RecipientName}}</a>
|
||||
</span>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
<button id="unclaimSubmit" class="btn btn-warning" type="submit" name="intent" value="unclaim_todo"
|
||||
disabled>Unclaim</button>
|
||||
<button id="completeSubmit" class="btn btn-success" type="submit" name="intent" value="complete_todo"
|
||||
disabled>Complete</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<p class="mb-0">When you claim gifts for others, they will appear here.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2>Your groups</h2>
|
||||
{{with .Groups}}
|
||||
<ul class="list-group">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
<a href="/groups/{{.Reference}}">{{.Name}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>You don't belong to any groups</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,33 +1,50 @@
|
|||
{{define "navbar"}}
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "body"}}
|
||||
<div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
|
||||
{{if .SuccessfulRegistration}}
|
||||
<div class="alert alert-success" role="alert">
|
||||
<p class="mb-0">Registration successful. Now you can login.</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{with .GeneralError}}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p class="mb-0">{{.}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
<form method="post">
|
||||
<div class="d-flex flex-column">
|
||||
<label>
|
||||
Username
|
||||
{{template "input" .Username}}
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
{{template "input" .Password}}
|
||||
</label>
|
||||
<div class="mb-3">
|
||||
<a href="/register">Register</a>
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
|
||||
{{if .SuccessfulRegistration}}
|
||||
<div class="alert alert-success" role="alert">
|
||||
<p class="mb-0">Registration successful. Now you can login.</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{with .GeneralError}}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p class="mb-0">{{.}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
<form method="post">
|
||||
<div class="d-flex flex-column">
|
||||
<label>
|
||||
Username
|
||||
{{template "input" .Username}}
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
{{template "input" .Password}}
|
||||
</label>
|
||||
<div class="mb-3">
|
||||
<a href="/register">Register</a>
|
||||
</div>
|
||||
<input class="btn btn-primary" type="submit" value="Login">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<input class="btn btn-primary" type="submit" value="Login">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,37 +1,50 @@
|
|||
{{define "navbar"}}
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "login_prompt"}}
|
||||
<a href="/">Login</a> or <a href="/register">register</a>
|
||||
{{end}}
|
||||
|
||||
{{define "body"}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2>{{.Username}}'s list</h2>
|
||||
{{if eq .GiftCount 0}}
|
||||
<p>{{.Username}} hasn't written any gift ideas!</p>
|
||||
<p>{{template "login_prompt"}} to add some! :^)</p>
|
||||
{{else}}
|
||||
{{if eq .GiftCount 1}}
|
||||
<p>{{.Username}} has only written one gift idea.</p>
|
||||
<p>{{template "login_prompt"}} to claim it, or add more! :^)</p>
|
||||
{{else}}
|
||||
<p>{{.Username}} has written {{.GiftCount}} gift ideas.</p>
|
||||
<p>{{template "login_prompt"}} to claim an idea, or add more! :^)</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2>{{.Username}}'s list</h2>
|
||||
{{if eq .GiftCount 0}}
|
||||
<p>{{.Username}} hasn't written any gift ideas!</p>
|
||||
<p>{{template "login_prompt"}} to add some! :^)</p>
|
||||
{{else}}
|
||||
{{if eq .GiftCount 1}}
|
||||
<p>{{.Username}} has only written one gift idea.</p>
|
||||
<p>{{template "login_prompt"}} to claim it, or add more! :^)</p>
|
||||
{{else}}
|
||||
<p>{{.Username}} has written {{.GiftCount}} gift ideas.</p>
|
||||
<p>{{template "login_prompt"}} to claim an idea, or add more! :^)</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,37 +1,50 @@
|
|||
{{define "navbar"}}
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "login_prompt"}}
|
||||
<a href="/">Login</a> or <a href="/register">register</a>
|
||||
{{end}}
|
||||
|
||||
{{define "body"}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2><em>{{.Group.Name}}</em> group members</h2>
|
||||
<p>{{template "login_prompt"}} to see your groups</p>
|
||||
{{with .Group.Members}}
|
||||
<ul class="list-group">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
{{.Name}}
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>There's nobody else in this group.</p>
|
||||
{{end}}
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="overflow-y-scroll flex-grow-1">
|
||||
<div class="container py-5">
|
||||
<section class="card">
|
||||
<div class="card-body">
|
||||
<h2><em>{{.Group.Name}}</em> group members</h2>
|
||||
<p>{{template "login_prompt"}} to see your groups</p>
|
||||
{{with .Group.Members}}
|
||||
<ul class="list-group">
|
||||
{{range .}}
|
||||
<li class="list-group-item">
|
||||
{{.Name}}
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>There's nobody else in this group.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,40 +1,57 @@
|
|||
{{define "navbar"}}
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{end}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
{{define "body"}}
|
||||
<div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>Your password will be stored in a safe, responsible manner; but don't trust my programming skills!</p>
|
||||
<p class="mb-0">Maybe use a password here that you don't use for important things...</p>
|
||||
</div>
|
||||
{{with .GeneralError}}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p class="mb-0">{{.}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
<form method="post">
|
||||
<div class="d-flex flex-column">
|
||||
<label>
|
||||
Username
|
||||
{{template "input" .Username}}
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
{{template "input" .Password}}
|
||||
</label>
|
||||
<label>
|
||||
Confirm password
|
||||
{{template "input" .ConfirmPassword}}
|
||||
</label>
|
||||
<input class="btn btn-primary" type="submit" value="Register">
|
||||
<body>
|
||||
<div style="height: 100svh;" class="d-flex flex-column">
|
||||
<div class="navbar navbar-expand-lg bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">Lishwist</div>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
|
||||
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<nav>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>Your password will be stored in a safe, responsible manner; but don't trust my programming skills!</p>
|
||||
<p class="mb-0">Maybe use a password here that you don't use for important things...</p>
|
||||
</div>
|
||||
{{with .GeneralError}}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p class="mb-0">{{.}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
<form method="post">
|
||||
<div class="d-flex flex-column">
|
||||
<label>
|
||||
Username
|
||||
{{template "input" .Username}}
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
{{template "input" .Password}}
|
||||
</label>
|
||||
<label>
|
||||
Confirm password
|
||||
{{template "input" .ConfirmPassword}}
|
||||
</label>
|
||||
<input class="btn btn-primary" type="submit" value="Register">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -29,29 +29,13 @@ func (p *InputProps) Validate() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
var Templates map[string]*template.Template
|
||||
var Template *template.Template
|
||||
|
||||
func init() {
|
||||
Templates = load()
|
||||
Template = load()
|
||||
}
|
||||
|
||||
func load() map[string]*template.Template {
|
||||
homeTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/home.gotmpl"))
|
||||
loginTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/login.gotmpl"))
|
||||
registerTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/register.gotmpl"))
|
||||
foreignTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/foreign_wishlist.gotmpl"))
|
||||
publicWishlistTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/public_foreign_wishlist.gotmpl"))
|
||||
errorTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/error_page.gotmpl"))
|
||||
groupTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/group_page.gotmpl"))
|
||||
publicGroupTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/public_group_page.gotmpl"))
|
||||
return map[string]*template.Template{
|
||||
"home.gotmpl": homeTmpl,
|
||||
"login.gotmpl": loginTmpl,
|
||||
"register.gotmpl": registerTmpl,
|
||||
"foreign_wishlist.gotmpl": foreignTmpl,
|
||||
"public_foreign_wishlist.gotmpl": publicWishlistTmpl,
|
||||
"error_page.gotmpl": errorTmpl,
|
||||
"group_page.gotmpl": groupTmpl,
|
||||
"public_group_page.gotmpl": publicGroupTmpl,
|
||||
}
|
||||
func load() *template.Template {
|
||||
t := template.Must(template.ParseGlob("templates/*.gotmpl"))
|
||||
return t
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue