Skip to content

Commit

Permalink
fixup! templates: render static pages using templ
Browse files Browse the repository at this point in the history
Signed-off-by: Sumner Evans <me@sumnerevans.com>
  • Loading branch information
sumnerevans committed May 25, 2024
1 parent 13b1e63 commit 487f203
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 109 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ toolchain go1.22.0

require (
github.com/a-h/templ v0.2.697
github.com/beeper/libserv v0.0.0-20231231202820-c7303abfc32c
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/mattn/go-sqlite3 v1.14.22
github.com/rs/zerolog v1.32.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/a-h/templ v0.2.697 h1:OILxtWvD0NRJaoCOiZCopRDPW8paroKlGsrAiHLykNE=
github.com/a-h/templ v0.2.697/go.mod h1:5cqsugkq9IerRNucNsI4DEamdHPsoGMQy99DzydLhM8=
github.com/beeper/libserv v0.0.0-20231231202820-c7303abfc32c h1:WqjRVgUO039eiISCjsZC4F9onOEV93DJAk6v33rsZzY=
github.com/beeper/libserv v0.0.0-20231231202820-c7303abfc32c/go.mod h1:b9FFm9y4mEm36G8ytVmS1vkNzJa0KepmcdVY+qf7qRU=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
Expand Down
92 changes: 28 additions & 64 deletions internal/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import (
"regexp"
"strings"

"github.com/a-h/templ"
"github.com/beeper/libserv/pkg/requestlog"
"github.com/rs/zerolog"
"github.com/rs/zerolog/hlog"
"github.com/sendgrid/sendgrid-go"

"github.com/ColoradoSchoolOfMines/mineshspc.com/database"
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/config"
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/contextkeys"
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/templates"

Check failure on line 20 in internal/application.go

View workflow job for this annotation

GitHub Actions / build

no required module provides package github.com/ColoradoSchoolOfMines/mineshspc.com/internal/templates; to add it:

Check failure on line 20 in internal/application.go

View workflow job for this annotation

GitHub Actions / lint

no required module provides package github.com/ColoradoSchoolOfMines/mineshspc.com/internal/templates; to add it:

Check failure on line 20 in internal/application.go

View workflow job for this annotation

GitHub Actions / lint

no required module provides package github.com/ColoradoSchoolOfMines/mineshspc.com/internal/templates; to add it:
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/templates/partials"
"github.com/ColoradoSchoolOfMines/mineshspc.com/website"
Expand Down Expand Up @@ -94,41 +97,6 @@ type renderInfo struct {
RedirectIfLoggedIn bool
}

type ContextKey string

const (
ContextKeyLoggedInTeacher ContextKey = "com.mineshspc.logged_in_user"
)

type Info struct {
config config.Configuration
pageName string
}

func (i *Info) Title() string {
return i.pageName
}

func (i *Info) HostedByHTML() template.HTML {
return i.config.HostedByHTML
}

func (i *Info) PageName() partials.PageName {
return partials.PageName(strings.ToLower(i.pageName))
}

func (i *Info) RegistrationEnabled() bool {
return i.config.RegistrationEnabled
}

func (*Info) Username(ctx context.Context) string {
if loggedInUser, ok := ctx.Value(ContextKeyLoggedInTeacher).(*database.Teacher); ok {
return loggedInUser.Name
} else {
return ""
}
}

func (a *Application) Start() {
a.Log.Info().Msg("connecting to sendgrid")
a.SendGridClient = sendgrid.NewSendClient(a.Config.SendgridAPIKey)
Expand All @@ -140,35 +108,30 @@ func (a *Application) Start() {

noArgs := func(r *http.Request) map[string]any { return nil }

router.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
info := Info{config: a.Config, pageName: "Home"}
ctx := r.Context()
user, err := a.GetLoggedInTeacher(r)
if err == nil {
ctx = context.WithValue(ctx, ContextKeyLoggedInTeacher, user)
}
templates.Base(&info, templates.Home(&info)).Render(ctx, w)
})

router.HandleFunc("GET /info", func(w http.ResponseWriter, r *http.Request) {
info := Info{config: a.Config, pageName: "Info"}
ctx := r.Context()
user, err := a.GetLoggedInTeacher(r)
if err == nil {
ctx = context.WithValue(ctx, ContextKeyLoggedInTeacher, user)
}
templates.Base(&info, templates.Info()).Render(ctx, w)
})

router.HandleFunc("GET /authors", func(w http.ResponseWriter, r *http.Request) {
info := Info{config: a.Config, pageName: "Authors"}
ctx := r.Context()
user, err := a.GetLoggedInTeacher(r)
if err == nil {
ctx = context.WithValue(ctx, ContextKeyLoggedInTeacher, user)
}
templates.Base(&info, templates.Authors()).Render(ctx, w)
})
// Static pages
staticPages2 := map[string]struct {
title string
pageName partials.PageName
content templ.Component
}{
"GET /{$}": {"Home", partials.PageNameHome, templates.Home()},
"GET /info": {"Info", partials.PageNameInfo, templates.Info()},
"GET /authors": {"Authors", "", templates.Authors()},
}
for path, pageInfo := range staticPages2 {
router.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user, err := a.GetLoggedInTeacher(r)
if err == nil {
ctx = context.WithValue(ctx, contextkeys.ContextKeyLoggedInTeacher, user)
}
if len(pageInfo.pageName) > 0 {
ctx = context.WithValue(ctx, contextkeys.ContextKeyPageName, pageInfo.pageName)
}
ctx = context.WithValue(ctx, contextkeys.ContextKeyRegistrationEnabled, a.Config.RegistrationEnabled)
templates.Base(pageInfo.title, pageInfo.content).Render(ctx, w)
})
}

// Static pages
staticPages := map[string]struct {
Expand Down Expand Up @@ -307,6 +270,7 @@ func (a *Application) Start() {
router.HandleFunc("GET /volunteer/checkin", a.HandleVolunteerCheckIn)

var handler http.Handler = router
handler = requestlog.AccessLogger(false)(handler)
handler = hlog.RequestIDHandler("request_id", "RequestID")(handler)
handler = hlog.NewHandler(*a.Log)(handler)

Expand Down
10 changes: 10 additions & 0 deletions internal/contextkeys/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package contextkeys

type contextKey int

const (
ContextKeyLoggedInTeacher contextKey = iota
ContextKeyPageName
ContextKeyRegistrationEnabled
ContextKeyHostedByHTML
)
14 changes: 4 additions & 10 deletions internal/templates/base.templ
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ package templates

import "github.com/ColoradoSchoolOfMines/mineshspc.com/internal/templates/partials"

type BaseInfo interface {
partials.NavbarInfo
partials.FooterInfo
Title() string
}

templ Base(info BaseInfo, content templ.Component) {
templ Base(title string, content templ.Component) {
<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -19,7 +13,7 @@ templ Base(info BaseInfo, content templ.Component) {
name="description"
content="The CS@Mines High School Programming Competition is a competition for high school students to write programs that solve problems."
/>
<title>{ info.Title() } | CS@Mines High School Programming Competition</title>
<title>{ title } | CS@Mines High School Programming Competition</title>
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"/>
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png"/>
Expand Down Expand Up @@ -49,11 +43,11 @@ templ Base(info BaseInfo, content templ.Component) {
/>
</head>
<body class="pb-4 shadow">
@partials.Navbar(info)
@partials.Navbar()
<div class="content">
@content
</div>
@partials.Footer(info)
@partials.Footer()
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script>
</body>
</html>
Expand Down
15 changes: 10 additions & 5 deletions internal/templates/home.templ
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package templates

type HomeInfo interface {
RegistrationEnabled() bool
import (
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/contextkeys"
)

func RegistrationEnabled(ctx context.Context) bool {
enabled, ok := ctx.Value(contextkeys.ContextKeyRegistrationEnabled).(bool)
return ok && enabled
}

templ Home(info HomeInfo) {
templ Home() {
<div class="hero text-center bg-white mb-4 py-4 shadow">
<div class="mt-4 pt-4">
<a href="https://cs.mines.edu" target="_blank">
Expand All @@ -16,11 +21,11 @@ templ Home(info HomeInfo) {
<!-- <h2 class="mb-2">The 2024 competition will be held April 20th, 2024.</h2> -->
<p class="registration-info mb-4">
Engage in exciting problems at the Mines HSPC!
if info.RegistrationEnabled() {
if RegistrationEnabled(ctx) {
Registration is now open for the Spring 2024 competition.
}
</p>
if info.RegistrationEnabled() {
if RegistrationEnabled(ctx) {
<p class="registration-info mb-4">
<!-- <span class="badge text-bg-danger py-2 px-4 me-4 fs-5"><b>Registration Deadline</b></span> -->
The registration deadline is <b>April 13th</b>
Expand Down
15 changes: 9 additions & 6 deletions internal/templates/partials/footer.templ
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package partials

import "html/template"
import (
"html/template"
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/contextkeys"
)

type FooterInfo interface {
HostedByHTML() template.HTML
// TODO make more things configurable
func GetHostedByHTML(ctx context.Context) template.HTML {
hostedByHTML, _ := ctx.Value(contextkeys.ContextKeyLoggedInTeacher).(template.HTML)
return hostedByHTML
}

templ Footer(info FooterInfo) {
templ Footer() {
<footer class="footer mt-4 pt-4 ps-4 pe-4">
<div class="row">
<div class="col text-center text-secondary">
Expand All @@ -32,7 +35,7 @@ templ Footer(info FooterInfo) {
source
code
</a>.
@templ.Raw(info.HostedByHTML())
@templ.Raw(GetHostedByHTML(ctx))
</p>
</div>
</div>
Expand Down
56 changes: 32 additions & 24 deletions internal/templates/partials/navbar.templ
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package partials

type PageName string

const (
PageNameHome PageName = "home"
PageNameInfo PageName = "info"
PageNameRules PageName = "rules"
PageNameRegister PageName = "register"
PageNameFAQ PageName = "faq"
PageNameArchive PageName = "archive"
import (
"github.com/ColoradoSchoolOfMines/mineshspc.com/database"
"github.com/ColoradoSchoolOfMines/mineshspc.com/internal/contextkeys"
)

type NavbarInfo interface {
PageName() PageName
RegistrationEnabled() bool
Username(ctx context.Context) string
// TODO make more things configurable?
func RegistrationEnabled(ctx context.Context) bool {
enabled, ok := ctx.Value(contextkeys.ContextKeyRegistrationEnabled).(bool)
return ok && enabled
}

func GetPageName(ctx context.Context) PageName {
if pageName, ok := ctx.Value(contextkeys.ContextKeyPageName).(PageName); ok {
return pageName
} else {
return ""
}
}

func GetUsername(ctx context.Context) string {
if loggedInUser, ok := ctx.Value(contextkeys.ContextKeyLoggedInTeacher).(*database.Teacher); ok {
return loggedInUser.Name
} else {
return ""
}
}

func getNavLinkClasses(activePageName, pageName PageName) []string {
Expand All @@ -26,7 +34,7 @@ func getNavLinkClasses(activePageName, pageName PageName) []string {
return classes
}

templ Navbar(info NavbarInfo) {
templ Navbar() {
<nav class="navbar sticky-top navbar-expand-lg navbar-light shadow">
<div class="container-fluid">
<button
Expand All @@ -53,7 +61,7 @@ templ Navbar(info NavbarInfo) {
</a>
<li class="nav-item">
<a
class={ getNavLinkClasses(info.PageName(), "home") }
class={ getNavLinkClasses(GetPageName(ctx), "home") }
id="home-link"
aria-current="page"
href="/"
Expand All @@ -64,24 +72,24 @@ templ Navbar(info NavbarInfo) {
</li>
<li class="nav-item">
<a
class={ getNavLinkClasses(info.PageName(), "info") }
class={ getNavLinkClasses(GetPageName(ctx), "info") }
id="info-link"
aria-current="page"
href="/info"
>Info</a>
</li>
<li class="nav-item">
<a
class={ getNavLinkClasses(info.PageName(), "rules") }
class={ getNavLinkClasses(GetPageName(ctx), "rules") }
id="rules-link"
aria-current="page"
href="/rules"
>Rules</a>
</li>
if info.RegistrationEnabled() {
if RegistrationEnabled(ctx) {
<li class="nav-item">
<a
class={ getNavLinkClasses(info.PageName(), "register") }
class={ getNavLinkClasses(GetPageName(ctx), "register") }
id="register-link"
aria-current="page"
href="/register"
Expand All @@ -90,24 +98,24 @@ templ Navbar(info NavbarInfo) {
}
<li class="nav-item">
<a
class={ getNavLinkClasses(info.PageName(), "faq") }
class={ getNavLinkClasses(GetPageName(ctx), "faq") }
id="faq-link"
aria-current="page"
href="/faq"
>FAQ</a>
</li>
<li class="nav-item">
<a
class={ getNavLinkClasses(info.PageName(), "archive") }
class={ getNavLinkClasses(GetPageName(ctx), "archive") }
id="archive-link"
aria-current="page"
href="/archive"
>Archive</a>
</li>
</ul>
<div class="logged-in-user nav-link small text-secondary me-4">
if len(info.Username(ctx)) > 0 {
Welcome <a href="/register/teacher/teams">{ info.Username(ctx) }</a>
if len(GetUsername(ctx)) > 0 {
Welcome <a href="/register/teacher/teams">{ GetUsername(ctx) }</a>
<span class="mx-2">|</span>
<a href="/register/teacher/logout">Logout</a>
} else {
Expand Down
12 changes: 12 additions & 0 deletions internal/templates/partials/pagenames.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package partials

type PageName string

const (
PageNameHome PageName = "home"
PageNameInfo PageName = "info"
PageNameRules PageName = "rules"
PageNameRegister PageName = "register"
PageNameFAQ PageName = "faq"
PageNameArchive PageName = "archive"
)

0 comments on commit 487f203

Please sign in to comment.