Compare commits

..

No commits in common. "609ccfc0c4be94c35762f35a55ca4504989506b4" and "9c9e0ebaff9603444074fc9ecdec143a4bcb4671" have entirely different histories.

20 changed files with 308 additions and 191 deletions

View File

@ -5,7 +5,6 @@ import (
) )
type RegisterProps struct { type RegisterProps struct {
Navbar templates.NavCollapse
GeneralError string `json:",omitempty"` GeneralError string `json:",omitempty"`
Username templates.InputProps Username templates.InputProps
Password templates.InputProps Password templates.InputProps
@ -37,7 +36,6 @@ func (p *RegisterProps) Validate() (valid bool) {
func NewRegisterProps(usernameVal, passwordVal, confirmPassVal string) *RegisterProps { func NewRegisterProps(usernameVal, passwordVal, confirmPassVal string) *RegisterProps {
return &RegisterProps{ return &RegisterProps{
Navbar: templates.DefaultNavCollapse(),
GeneralError: "", GeneralError: "",
Username: templates.InputProps{ Username: templates.InputProps{
Name: "username", Name: "username",

View File

@ -1,4 +1,7 @@
top_level=$(git rev-parse --show-toplevel) top_level=$(git rev-parse --show-toplevel)
git_version=$($top_level/scripts/git-version) git_version=$($top_level/scripts/git-version)
export GOOS=linux
export GOARCH=amd64
go build -ldflags=-X=lishwist/http/env.GitVersion=$git_version . go build -ldflags=-X=lishwist/http/env.GitVersion=$git_version .

View File

@ -2,7 +2,6 @@ package response
import ( import (
"fmt" "fmt"
"lishwist/http/templates"
"net/http" "net/http"
"github.com/Teajey/rsvp" "github.com/Teajey/rsvp"
@ -12,19 +11,10 @@ func NotFound() rsvp.Response {
return Error(http.StatusNotFound, "Page not found") return Error(http.StatusNotFound, "Page not found")
} }
type errorProps struct {
Navbar templates.NavCollapse
Message string
}
func Error(status int, format string, a ...any) rsvp.Response { func Error(status int, format string, a ...any) rsvp.Response {
return rsvp.Response{ return rsvp.Response{
Body: errorProps{ Body: fmt.Sprintf(format, a...),
Message: fmt.Sprintf(format, a...),
Navbar: templates.DefaultNavCollapse(),
},
Status: status, Status: status,
TemplateName: "error_page.gotmpl",
} }
} }

View File

@ -13,7 +13,7 @@ import (
) )
type AccountProps struct { type AccountProps struct {
Navbar templates.NavCollapse CurrentUsername string
GeneralError string `json:",omitempty"` GeneralError string `json:",omitempty"`
PasswordFromAdmin bool `json:",omitempty"` PasswordFromAdmin bool `json:",omitempty"`
Password templates.InputProps Password templates.InputProps
@ -41,7 +41,7 @@ func (p *AccountProps) Validate() (valid bool) {
func NewAccountProps(username string, passwordFromAdmin bool, passwordVal, confirmPassVal string) *AccountProps { func NewAccountProps(username string, passwordFromAdmin bool, passwordVal, confirmPassVal string) *AccountProps {
return &AccountProps{ return &AccountProps{
Navbar: templates.UserNavCollapse(username, false), CurrentUsername: username,
PasswordFromAdmin: passwordFromAdmin, PasswordFromAdmin: passwordFromAdmin,
Password: templates.InputProps{ Password: templates.InputProps{
Type: "password", Type: "password",

View File

@ -3,7 +3,6 @@ package routing
import ( import (
lishwist "lishwist/core" lishwist "lishwist/core"
"lishwist/http/response" "lishwist/http/response"
"lishwist/http/templates"
"log" "log"
"net/http" "net/http"
@ -11,7 +10,6 @@ import (
) )
type foreignWishlistProps struct { type foreignWishlistProps struct {
Navbar templates.NavCollapse
CurrentUserId string CurrentUserId string
CurrentUserName string CurrentUserName string
Username string Username string
@ -37,12 +35,11 @@ func ForeignWishlist(app *lishwist.Session, session *response.Session, h http.He
log.Printf("%q couldn't get wishes of other user %q: %s\n", user.Name, otherUser.Name, err) log.Printf("%q couldn't get wishes of other user %q: %s\n", user.Name, otherUser.Name, err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching this user :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching this user :(")
} }
p := foreignWishlistProps{Navbar: templates.UserNavCollapse(user.Name, user.PasswordFromAdmin), CurrentUserId: user.Id, Username: otherUser.Name, Gifts: wishes} p := foreignWishlistProps{CurrentUserId: user.Id, CurrentUserName: user.Name, Username: otherUser.Name, Gifts: wishes}
return response.Data("foreign_wishlist.gotmpl", p) return response.Data("foreign_wishlist.gotmpl", p)
} }
type publicWishlistProps struct { type publicWishlistProps struct {
Navbar templates.NavCollapse
Username string Username string
GiftCount int GiftCount int
} }
@ -62,6 +59,6 @@ func PublicWishlist(s *response.Session, h http.Header, r *http.Request) rsvp.Re
log.Printf("Couldn't get wishes of user %q on public wishlist: %s\n", otherUser.Name, err) log.Printf("Couldn't get wishes of user %q on public wishlist: %s\n", otherUser.Name, err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching this user :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching this user :(")
} }
p := publicWishlistProps{Navbar: templates.DefaultNavCollapse(), Username: otherUser.Name, GiftCount: giftCount} p := publicWishlistProps{Username: otherUser.Name, GiftCount: giftCount}
return response.Data("public_foreign_wishlist.gotmpl", p) return response.Data("public_foreign_wishlist.gotmpl", p)
} }

View File

@ -7,14 +7,13 @@ import (
lishwist "lishwist/core" lishwist "lishwist/core"
"lishwist/http/response" "lishwist/http/response"
"lishwist/http/templates"
"github.com/Teajey/rsvp" "github.com/Teajey/rsvp"
) )
type GroupProps struct { type GroupProps struct {
Navbar templates.NavCollapse
Group *lishwist.Group Group *lishwist.Group
CurrentUsername string
} }
func AdminGroup(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response { func AdminGroup(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Response {
@ -32,8 +31,8 @@ func AdminGroup(app *lishwist.Session, h http.Header, r *http.Request) rsvp.Resp
group.Members = slices.Delete(group.Members, index, index+1) group.Members = slices.Delete(group.Members, index, index+1)
} }
p := GroupProps{ p := GroupProps{
Navbar: templates.UserNavCollapse(user.Name, user.PasswordFromAdmin),
Group: group, Group: group,
CurrentUsername: user.Name,
} }
return response.Data("group_page.gotmpl", p) return response.Data("group_page.gotmpl", p)
} }
@ -55,8 +54,8 @@ func Group(app *lishwist.Session, session *response.Session, h http.Header, r *h
index := group.MemberIndex(user.Id) index := group.MemberIndex(user.Id)
group.Members = slices.Delete(group.Members, index, index+1) group.Members = slices.Delete(group.Members, index, index+1)
p := GroupProps{ p := GroupProps{
Navbar: templates.UserNavCollapse(user.Name, user.PasswordFromAdmin),
Group: group, Group: group,
CurrentUsername: user.Name,
} }
return response.Data("group_page.gotmpl", p) return response.Data("group_page.gotmpl", p)
} }
@ -68,11 +67,7 @@ func PublicGroup(s *response.Session, h http.Header, r *http.Request) rsvp.Respo
log.Printf("Couldn't get group: %s\n", err) log.Printf("Couldn't get group: %s\n", err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching this group :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching this group :(")
} }
if group == nil {
return response.Error(http.StatusNotFound, "Group not found")
}
p := GroupProps{ p := GroupProps{
Navbar: templates.DefaultNavCollapse(),
Group: group, Group: group,
} }
return response.Data("public_group_page.gotmpl", p) return response.Data("public_group_page.gotmpl", p)

View File

@ -7,16 +7,18 @@ import (
lishwist "lishwist/core" lishwist "lishwist/core"
"lishwist/http/env" "lishwist/http/env"
"lishwist/http/response" "lishwist/http/response"
"lishwist/http/templates"
"github.com/Teajey/rsvp" "github.com/Teajey/rsvp"
) )
type HomeProps struct { type HomeProps struct {
Navbar templates.NavCollapse Username string
Gifts []lishwist.Wish Gifts []lishwist.Wish
Todo []lishwist.Wish Todo []lishwist.Wish
Reference string
HostUrl string
Groups []lishwist.Group Groups []lishwist.Group
AccountAlert bool
} }
func Home(app *lishwist.Session, session *response.Session, h http.Header, r *http.Request) rsvp.Response { func Home(app *lishwist.Session, session *response.Session, h http.Header, r *http.Request) rsvp.Response {
@ -36,10 +38,7 @@ func Home(app *lishwist.Session, session *response.Session, h http.Header, r *ht
log.Printf("Failed to get groups: %s\n", err) log.Printf("Failed to get groups: %s\n", err)
return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(") return response.Error(http.StatusInternalServerError, "An error occurred while fetching your wishlist :(")
} }
p := HomeProps{Navbar: templates.NavCollapse{ p := HomeProps{Username: user.Name, Gifts: gifts, Todo: todo, Reference: user.Reference, HostUrl: env.Configuration.HostUrl, Groups: groups, AccountAlert: user.PasswordFromAdmin}
User: &templates.User{Name: user.Name, CopyList: &templates.CopyList{Domain: env.Configuration.HostUrl, Reference: user.Reference}},
AccountLink: &templates.AccountLink{Alert: user.PasswordFromAdmin},
}, Gifts: gifts, Todo: todo, Groups: groups}
return response.Data("home.gotmpl", p) return response.Data("home.gotmpl", p)
} }

View File

@ -33,16 +33,13 @@ func Login(s *response.Session, h http.Header, r *http.Request) rsvp.Response {
} }
func LoginPost(session *response.Session, h http.Header, r *http.Request) rsvp.Response { func LoginPost(session *response.Session, h http.Header, r *http.Request) rsvp.Response {
username, password, ok := r.BasicAuth()
if !ok {
err := r.ParseForm() err := r.ParseForm()
if err != nil { if err != nil {
return response.Error(http.StatusBadRequest, "Failed to parse form") return response.Error(http.StatusBadRequest, "Failed to parse form")
} }
username = r.Form.Get("username") username := r.Form.Get("username")
password = r.Form.Get("password") password := r.Form.Get("password")
}
props := api.NewLoginProps(username, password) props := api.NewLoginProps(username, password)

View File

@ -29,20 +29,14 @@ func Register(session *response.Session, h http.Header, r *http.Request) rsvp.Re
} }
func RegisterPost(s *response.Session, h http.Header, r *http.Request) rsvp.Response { func RegisterPost(s *response.Session, h http.Header, r *http.Request) rsvp.Response {
var confirmPassword string
username, newPassword, ok := r.BasicAuth()
if ok {
confirmPassword = newPassword
} else {
err := r.ParseForm() err := r.ParseForm()
if err != nil { if err != nil {
return response.Error(http.StatusBadRequest, "Failed to parse form") return response.Error(http.StatusBadRequest, "Failed to parse form")
} }
username = r.Form.Get("username") username := r.Form.Get("username")
newPassword = r.Form.Get("newPassword") newPassword := r.Form.Get("newPassword")
confirmPassword = r.Form.Get("confirmPassword") confirmPassword := r.Form.Get("confirmPassword")
}
props := api.NewRegisterProps(username, newPassword, confirmPassword) props := api.NewRegisterProps(username, newPassword, confirmPassword)
@ -55,7 +49,7 @@ func RegisterPost(s *response.Session, h http.Header, r *http.Request) rsvp.Resp
return rsvp.SeeOther(r.URL.Path, props) return rsvp.SeeOther(r.URL.Path, props)
} }
_, err := lishwist.Register(username, newPassword) _, err = lishwist.Register(username, newPassword)
if err != nil { if err != nil {
if errors.Is(err, lishwist.ErrorUsernameTaken) { if errors.Is(err, lishwist.ErrorUsernameTaken) {
props.Username.Error = "Username is taken" props.Username.Error = "Username is taken"

View File

@ -7,7 +7,41 @@
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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>
<div class="overflow-y-scroll flex-grow-1"> <div class="overflow-y-scroll flex-grow-1">
<div class="container py-5"> <div class="container py-5">
{{with .GeneralError}} {{with .GeneralError}}

View File

@ -41,62 +41,28 @@
</script> </script>
{{end}} {{end}}
{{define "navbar"}} {{define "boilerplate"}}
<head>
{{template "head" .}}
</head>
<body>
<div style="height: 100svh;" class="d-flex flex-column">
<div class="navbar navbar-expand-lg bg-body-tertiary"> <div class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-brand">Lishwist</div> <div class="navbar-brand">Lishwist</div>
{{with .}}
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle" <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation"> aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>{{if and .AccountLink .AccountLink.Alert}} <span <span class="navbar-toggler-icon"></span>
class="badge text-bg-danger">!</span>{{end}}
</button> </button>
<div class="collapse navbar-collapse" id="navbarToggle"> <div class="collapse navbar-collapse" id="navbarToggle">
{{with .Links}} {{template "navbar" .}}
<nav>
<ul class="navbar-nav">
{{range .}}
<li class="nav-item">
<a class="nav-link" href="{{.Href}}">{{.Name}}</a>
</li>
{{end}}
</ul>
</nav>
{{end}}
<div class="flex-grow-1"></div>
{{with .User}}
<ul class="navbar-nav">
{{with .CopyList}}
<li class="nav-item"><button class="btn btn-success"
onclick="navigator.clipboard.writeText('{{.Domain}}/lists/{{.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>
{{end}}
<li class="nav-item">
<div class="dropdown">
<button class="nav-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
Logged in as '{{.Name}}'
</button>
<ul class="dropdown-menu">
{{with $.AccountLink}}
<li>
<a class="dropdown-item" href="/account">Account{{if .Alert}} <span
class="badge text-bg-danger">!</span>{{end}}</a>
</li>
{{end}}
<li>
<form class="d-contents" method="post" action="/logout">
<button class="dropdown-item" type="submit">Logout</button>
</form>
</li>
</ul>
</div>
</li>
</ul>
{{end}}
</div>
{{end}}
</div> </div>
</div> </div>
</div>
{{template "body" .}}
</div>
</body>
{{end}} {{end}}
{{define "login_prompt"}} {{define "login_prompt"}}

View File

@ -1,12 +1,29 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
<p class="mb-0">{{.Message}}</p> <p class="mb-0">{{.Message}}</p>

View File

@ -1,12 +1,46 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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>
<div class="overflow-y-scroll flex-grow-1"> <div class="overflow-y-scroll flex-grow-1">
<div class="container py-5"> <div class="container py-5">
<section class="card"> <section class="card">

View File

@ -1,12 +1,46 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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>
<div class="overflow-y-scroll flex-grow-1"> <div class="overflow-y-scroll flex-grow-1">
<div class="container py-5"> <div class="container py-5">
<section class="card"> <section class="card">

View File

@ -2,12 +2,47 @@
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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>{{if .AccountAlert}} <span
class="badge text-bg-danger">!</span>{{end}}
</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}}/lists/{{.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}}'{{if .AccountAlert}} <span class="badge text-bg-danger">!</span>{{end}}
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="/account">Account{{if .AccountAlert}} <span
class="badge text-bg-danger">!</span>{{end}}</a>
</li>
<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>
<div class="overflow-y-scroll flex-grow-1"> <div class="overflow-y-scroll flex-grow-1">
<div class="container py-5"> <div class="container py-5">
<section class="card mb-4"> <section class="card mb-4">

View File

@ -1,12 +1,22 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar"}} <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"> <div class="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
{{if .SuccessfulRegistration}} {{if .SuccessfulRegistration}}
<div class="alert alert-success" role="alert"> <div class="alert alert-success" role="alert">

View File

@ -1,12 +1,29 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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="overflow-y-scroll flex-grow-1"> <div class="overflow-y-scroll flex-grow-1">
<div class="container py-5"> <div class="container py-5">
<section class="card"> <section class="card">

View File

@ -1,12 +1,29 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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="overflow-y-scroll flex-grow-1"> <div class="overflow-y-scroll flex-grow-1">
<div class="container py-5"> <div class="container py-5">
<section class="card"> <section class="card">

View File

@ -1,12 +1,29 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
{{template "head"}} {{template "head" .}}
</head> </head>
<body> <body>
<div style="height: 100svh;" class="d-flex flex-column"> <div style="height: 100svh;" class="d-flex flex-column">
{{template "navbar" .Navbar}} <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="container d-flex flex-grow-1 justify-content-center align-items-center flex-column">
<div class="alert alert-warning" role="alert"> <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>Your password will be stored in a safe, responsible manner; but don't trust my programming skills!</p>

View File

@ -5,43 +5,6 @@ import (
"html/template" "html/template"
) )
type AccountLink struct {
Alert bool
}
type Link struct {
Href string
Name string
}
type CopyList struct {
Domain string
Reference string
}
type User struct {
Name string
CopyList *CopyList
}
type NavCollapse struct {
User *User
AccountLink *AccountLink
Links []Link
}
func DefaultNavCollapse() NavCollapse {
return NavCollapse{Links: []Link{{Href: "/", Name: "Home"}}}
}
func UserNavCollapse(username string, accountAlert bool) NavCollapse {
return NavCollapse{
Links: []Link{{Href: "/", Name: "Home"}},
User: &User{Name: username},
AccountLink: &AccountLink{Alert: accountAlert},
}
}
type InputProps struct { type InputProps struct {
Type string `json:",omitempty"` Type string `json:",omitempty"`
Name string Name string