Convert templates to partials

This commit is contained in:
Jan Bader 2021-12-02 15:00:53 +00:00
parent 67f7022b90
commit 77ae9d2dfd
16 changed files with 261 additions and 237 deletions

View File

@ -39,5 +39,5 @@ func (h *Handler) accounts(c *gin.Context) {
Accounts: accounts, Accounts: accounts,
} }
c.HTML(http.StatusOK, "accounts", d) c.HTML(http.StatusOK, "accounts.html", d)
} }

View File

@ -48,5 +48,5 @@ func (h *Handler) budget(c *gin.Context) {
Transactions: transactions, Transactions: transactions,
} }
c.HTML(http.StatusOK, "budget", d) c.HTML(http.StatusOK, "budget.html", d)
} }

View File

@ -25,7 +25,7 @@ func (h *Handler) dashboard(c *gin.Context) {
Token: token, Token: token,
Budgets: budgets, Budgets: budgets,
} }
c.HTML(http.StatusOK, "dashboard", d) c.HTML(http.StatusOK, "dashboard.html", d)
} }
type DashboardData struct { type DashboardData struct {

View File

@ -6,8 +6,6 @@ import (
"net/http" "net/http"
"time" "time"
"html/template"
"git.javil.eu/jacob1123/budgeteer" "git.javil.eu/jacob1123/budgeteer"
"git.javil.eu/jacob1123/budgeteer/bcrypt" "git.javil.eu/jacob1123/budgeteer/bcrypt"
"git.javil.eu/jacob1123/budgeteer/postgres" "git.javil.eu/jacob1123/budgeteer/postgres"
@ -34,8 +32,12 @@ const (
func (h *Handler) Serve() { func (h *Handler) Serve() {
router := gin.Default() router := gin.Default()
templ := template.Must(template.New("").Funcs(router.FuncMap).ParseFS(web.Templates, "*")) templates, err := NewTemplates(router.FuncMap)
router.SetHTMLTemplate(templ) if err != nil {
panic(err)
}
router.HTMLRender = templates
static, err := fs.Sub(web.Static, "static") static, err := fs.Sub(web.Static, "static")
if err != nil { if err != nil {
@ -43,7 +45,7 @@ func (h *Handler) Serve() {
} }
router.StaticFS("/static", http.FS(static)) router.StaticFS("/static", http.FS(static))
router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index", nil) }) router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index.html", nil) })
router.GET("/login", h.login) router.GET("/login", h.login)
router.GET("/register", h.register) router.GET("/register", h.register)
authenticatedFrontend := router.Group("") authenticatedFrontend := router.Group("")
@ -180,7 +182,7 @@ func (h *Handler) login(c *gin.Context) {
return return
} }
c.HTML(http.StatusOK, "login", nil) c.HTML(http.StatusOK, "login.html", nil)
} }
func (h *Handler) register(c *gin.Context) { func (h *Handler) register(c *gin.Context) {
@ -189,7 +191,7 @@ func (h *Handler) register(c *gin.Context) {
return return
} }
c.HTML(http.StatusOK, "register", nil) c.HTML(http.StatusOK, "register.html", nil)
} }
func logout(c *gin.Context) { func logout(c *gin.Context) {

45
http/templates.go Normal file
View File

@ -0,0 +1,45 @@
package http
import (
"fmt"
"html/template"
"io/fs"
"git.javil.eu/jacob1123/budgeteer/web"
"github.com/gin-gonic/gin/render"
)
type Templates struct {
templates map[string]*template.Template
}
func NewTemplates(funcMap template.FuncMap) (*Templates, error) {
templates, err := fs.Glob(web.Templates, "*.tpl")
if err != nil {
return nil, err
}
result := &Templates{
templates: make(map[string]*template.Template, 0),
}
pages, err := fs.Glob(web.Templates, "*.html")
for _, page := range pages {
allTemplates := append([]string{page}, templates...)
tpl, err := template.New(page).Funcs(funcMap).ParseFS(web.Templates, allTemplates...)
fmt.Printf("page: %s, templates: %v\n", page, templates)
if err != nil {
return nil, err
}
result.templates[page] = tpl
}
return result, nil
}
func (tpl *Templates) Instance(name string, obj interface{}) render.Render {
return render.HTML{
Template: tpl.templates[name],
Name: name,
Data: obj,
}
}

View File

@ -1,23 +1,17 @@
{{define "accounts"}} {{define "title"}}
<!DOCTYPE html> Accounts
<html> {{end}}
<head>
<title>Budgets</title> {{define "new"}}
{{end}}
{{template "head"}}
</head> {{template "base" .}}
<body>
<div class="container" id="head"> {{define "main"}}
Budgeteer - {{.Token.GetName}} {{range .Accounts}}
</div> <div class="budget-item">
<div class="container col-lg-12" id="content"> <a href="account/{{.ID}}">{{.Name}}</a>
{{range .Accounts}} <span class="time"></span>
<div class="budget-item"> </div>
<a href="account/{{.ID}}">{{.Name}}</a> {{end}}
<span class="time"></span>
</div>
{{end}}
</div>
</body>
</html>
{{end}} {{end}}

31
web/base.tpl Normal file
View File

@ -0,0 +1,31 @@
{{define "base"}}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="/static/css/bootstrap.min.css" rel="stylesheet" />
<link href="/static/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="/static/css/main.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://malsup.github.io/jquery.form.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/main.js"></script>
<title>{{template "title" .}} - Budgeteer</title>
{{block "more-head" .}}{{end}}
</head>
<body>
<div class="container" id="head">
{{template "title" .}}
</div>
<div class="container col-lg-12" id="content">
{{template "main" .}}
</div>
{{block "new" .}}{{end}}
</body>
</html>
{{end}}

View File

@ -1,32 +1,26 @@
{{define "budget"}} {{template "base" .}}
<!DOCTYPE html>
<html>
<head>
<title>Budgets</title>
{{template "head"}} {{define "title"}}Budget{{end}}
</head>
<body> {{define "new"}}
<div class="container" id="head"> {{template "transaction-new"}}
Budgeteer - {{.Token.GetName}} - {{.Budget.Name}} {{end}}
</div>
<div class="container"><a href="/budget/{{.Budget.ID}}/accounts">Go to Accounts</a></div> {{define "main"}}
<div class="budget-item"> <div class="container"><a href="/budget/{{.Budget.ID}}/accounts">Go to Accounts</a></div>
<a href="#newbudgetmodal" data-toggle="modal" data-target="#newbudgetmodal">New Budget</a> <div class="budget-item">
<span class="time"></span> <a href="#newbudgetmodal" data-toggle="modal" data-target="#newbudgetmodal">New Budget</a>
</div> <span class="time"></span>
<table class="container col-lg-12" id="content"> </div>
{{range .Transactions}} <table class="container col-lg-12" id="content">
<tr> {{range .Transactions}}
<td>{{.Date}}</td> <tr>
<td> <td>{{.Date}}</td>
<a href="transaction/{{.ID}}">{{.Memo.String}}</a> <td>
</td> <a href="transaction/{{.ID}}">{{.Memo.String}}</a>
<td>{{.Amount}}</td> </td>
</tr> <td>{{.Amount}}</td>
{{end}} </tr>
</table> {{end}}
{{template "transaction-new"}} </table>
</body>
</html>
{{end}} {{end}}

View File

@ -1,28 +1,22 @@
{{define "dashboard"}} {{define "title"}}
<!DOCTYPE html> Budgets
<html> {{end}}
<head>
<title>Budgets</title> {{define "new"}}
{{template "budget-new"}}
{{template "head"}} {{end}}
</head>
<body> {{template "base" .}}
<div class="container" id="head">
Budgeteer - {{.Token.GetName}} {{define "main"}}
</div> {{range .Budgets}}
<div class="container col-lg-12" id="content"> <div class="budget-item">
{{range .Budgets}} <a href="budget/{{.ID}}">{{.Name}}</a>
<div class="budget-item"> <span class="time"></span>
<a href="budget/{{.ID}}">{{.Name}}</a> </div>
<span class="time"></span> {{end}}
</div> <div class="budget-item">
{{end}} <a href="#newbudgetmodal" data-toggle="modal" data-target="#newbudgetmodal">New Budget</a>
<div class="budget-item"> <span class="time"></span>
<a href="#newbudgetmodal" data-toggle="modal" data-target="#newbudgetmodal">New Budget</a> </div>
<span class="time"></span>
</div>
</div>
{{template "budget-new"}}
</body>
</html>
{{end}} {{end}}

View File

@ -1,13 +0,0 @@
{{define "head"}}
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="/static/css/bootstrap.min.css" rel="stylesheet" />
<link href="/static/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="/static/css/main.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://malsup.github.io/jquery.form.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/main.js"></script>
{{end}}

View File

@ -1,21 +1,17 @@
{{define "index"}} {{define "title"}}
<!DOCTYPE html> Start
<html> {{end}}
<head>
<title>Budgeteer</title> {{define "new"}}
{{end}}
{{template "head"}}
</head> {{template "base" .}}
<body>
<div class="container" id="head"> {{define "main"}}
Budgeteer <div class="container col-md-8 col-ld-8" id="content">
</div> Willkommen bei Budgeteer, der neuen App für's Budget!
<div class="container col-md-8 col-ld-8" id="content"> </div>
Willkommen bei Budgeteer, der neuen App für's Budget! <div class="container col-md-4" id="login">
</div> <a href="/login">Login</a> or <a href="/login">register</a>
<div class="container col-md-4" id="login"> </div>
<a href="/login">Login</a>
</div>
</body>
</html>
{{end}} {{end}}

View File

@ -1,47 +1,38 @@
{{define "login"}} {{template "base" .}}
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
{{template "head"}} {{define "title"}}Login{{end}}
<script> {{define "more-head"}}
$(document).ready(function() { <script>
$('#invalidCredentials').hide(); $(document).ready(function() {
$('#loginForm').ajaxForm({ $('#invalidCredentials').hide();
success: function() { $('#loginForm').ajaxForm({
window.location.href = "/dashboard"; success: function() {
}, window.location.href = "/dashboard";
error: function() { },
$('#invalidCredentials').show(); error: function() {
} $('#invalidCredentials').show();
}); }
}); });
</script> });
</head> </script>
<body> {{end}}
<div class="container" id="head">
Budgeteer {{define "main"}}
</div> <form id="loginForm" action="/api/v1/user/login" method="POST" class="center-block">
<div class="container col-lg-12" id="content"> <div class="form-group">
<form id="loginForm" action="/api/v1/user/login" method="POST" class="center-block"> <label for="username">User</label>
<div class="form-group"> <input type="text" name="username" class="form-control" placeholder="User" />
<label for="username">User</label> </div>
<input type="text" name="username" class="form-control" placeholder="User" />
</div> <div class="form-group">
<label for="password">Password</label>
<div class="form-group"> <input type="password" name="password" class="form-control" placeholder="Password" />
<label for="password">Password</label> <p id="invalidCredentials">
<input type="password" name="password" class="form-control" placeholder="Password" /> The entered credentials are invalid
<p id="invalidCredentials"> </p>
The entered credentials are invalid </div>
</p>
</div> <input type="submit" value="Login" class="btn btn-default" />
</form>
<input type="submit" value="Login" class="btn btn-default" />
</form>
</div>
</body>
</html>
{{end}} {{end}}

View File

@ -1,78 +1,68 @@
{{define "register"}} {{define "title"}}Register{{end}}
<!DOCTYPE html>
<html>
<head>
<title>Registration</title>
{{template "head"}} {{template "base" .}}
<script> {{define "more-head"}}
function checkPasswordMatchUi() { <script>
if(checkPasswordMatch()) function checkPasswordMatchUi() {
$("#divCheckPasswordMatch").html("Passwords match."); if(checkPasswordMatch())
else $("#divCheckPasswordMatch").html("Passwords match.");
$("#divCheckPasswordMatch").html("Passwords do not match!"); else
$("#divCheckPasswordMatch").html("Passwords do not match!");
}
function checkPasswordMatch() {
var password = $("#password").val();
var confirmPassword = $("#password_confirm").val();
return password == confirmPassword;
}
$(document).ready(function () {
$("#password, #password_confirm").keyup(checkPasswordMatchUi);
$('#invalidCredentials').hide();
$('#loginForm').ajaxForm({
beforeSubmit: function(a, b, c) {
var match = checkPasswordMatch();
if(!match){
$("#divCheckPasswordMatch").fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300);
} }
return match;
function checkPasswordMatch() { },
var password = $("#password").val(); success: function() {
var confirmPassword = $("#password_confirm").val(); window.location.href = "/dashboard";
},
return password == confirmPassword; error: function() {
} $('#invalidCredentials').show();
}
$(document).ready(function () { });
$("#password, #password_confirm").keyup(checkPasswordMatchUi); });
$('#invalidCredentials').hide(); </script>
$('#loginForm').ajaxForm({ {{end}}
beforeSubmit: function(a, b, c) {
var match = checkPasswordMatch(); {{define "main"}}
if(!match){ <form id="loginForm" action="/api/v1/user/register" method="POST" class="center-block">
$("#divCheckPasswordMatch").fadeOut(300).fadeIn(300).fadeOut(300).fadeIn(300); <div class="form-group">
} <label for="email">E-Mail</label>
return match; <input type="text" name="email" class="form-control" placeholder="E-Mail" />
}, </div>
success: function() {
window.location.href = "/dashboard"; <div class="form-group">
}, <label for="name">Name</label>
error: function() { <input type="text" name="name" class="form-control" placeholder="Name" />
$('#invalidCredentials').show(); </div>
}
}); <div class="form-group">
}); <label for="password">Password</label>
</script> <input type="password" name="password" id="password" class="form-control" placeholder="Password" />
</head> <input type="password" id="password_confirm" class="form-control" placeholder="Verify password" />
<body> </div>
<div class="container" id="head">
Budgeteer <div id="divCheckPasswordMatch"></div>
</div>
<div class="container col-lg-12" id="content"> <div id="invalidCredentials">
<form id="loginForm" action="/api/v1/user/register" method="POST" class="center-block"> Username already exists
<div class="form-group"> </div>
<label for="email">E-Mail</label>
<input type="text" name="email" class="form-control" placeholder="E-Mail" /> <input type="submit" value="Login" class="form-control" />
</div> </form>
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" class="form-control" placeholder="Name" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" id="password" class="form-control" placeholder="Password" />
<input type="password" id="password_confirm" class="form-control" placeholder="Verify password" />
</div>
<div id="divCheckPasswordMatch"></div>
<div id="invalidCredentials">
Username already exists
</div>
<input type="submit" value="Login" class="form-control" />
</form>
</div>
</body>
</html>
{{end}} {{end}}

View File

@ -2,7 +2,7 @@ package web
import "embed" import "embed"
//go:embed *.html //go:embed *.html *.tpl
var Templates embed.FS var Templates embed.FS
//go:embed static //go:embed static