Get the main content of forum category index working

This commit is contained in:
Ben Visness 2021-05-03 17:45:17 -05:00
parent 5f763d334c
commit 15e716c097
12 changed files with 103 additions and 29 deletions

View File

@ -8574,6 +8574,9 @@ input[type=submit] {
background-color: #f0f0f0; background-color: #f0f0f0;
background-color: var(--forum-even-background); } background-color: var(--forum-even-background); }
.thread-list-item .latestpost {
width: 16.5rem; }
.thread { .thread {
color: black; color: black;
color: var(--fg-font-color); } color: var(--fg-font-color); }

View File

@ -21,6 +21,10 @@
@include usevar('background-color', 'forum-even-background'); @include usevar('background-color', 'forum-even-background');
} }
.thread-list-item .latestpost {
width: 16.5rem;
}
.thread { .thread {
@include usevar('color', 'fg-font-color'); @include usevar('color', 'fg-font-color');

View File

@ -2,6 +2,19 @@
{{ define "content" }} {{ define "content" }}
<div class="content-block"> <div class="content-block">
<div class="optionbar">
<div class="options">
{{ if .User }}
<a class="button new-thread" href="{{ printf "%s/t/new" .CategoryUrl }}"><span class="big">+</span> New Thread</a>
<a class="button" href="{{ printf "%s/markread" .CategoryUrl }}"><span class="big">&#x2713;</span> Mark threads here as read</a>
{{ else }}
<a class="button" href="{% url 'member_login' subdomain=request.subdomain %}">Log in to post a new thread</a>
{{ end }}
</div>
<div class="options">
{{ template "pagination.html" .Pagination }}
</div>
</div>
{{ range .Threads }} {{ range .Threads }}
{{ template "thread_list_item.html" . }} {{ template "thread_list_item.html" . }}
{{ end }} {{ end }}

View File

@ -9,9 +9,9 @@
<a class="logout" href="{{ url "/logout" }}"><span class="icon-logout"></span> Logout</a> <a class="logout" href="{{ url "/logout" }}"><span class="icon-logout"></span> Logout</a>
{{ else }} {{ else }}
<a class="register" id="register-link" href="{{ url "/member_register" }}">Register</a> <a class="register" id="register-link" href="{{ url "/member_register" }}">Register</a>
<a class="login" id="login-link" href="{{ currentprojecturl "/login" }}">Log in</a> <a class="login" id="login-link" href="{{ projecturl "/login" .Project }}">Log in</a>
<div id="login-popup"> <div id="login-popup">
<form action="{{ currentprojecturl "/login" }}" method="post"> <form action="{{ projecturl "/login" .Project }}" method="post">
{{/* TODO: CSRF */}} {{/* TODO: CSRF */}}
<table> <table>
<tr> <tr>
@ -38,24 +38,24 @@
</a> </a>
<div class="items flex items-center justify-center justify-start-ns"> <div class="items flex items-center justify-center justify-start-ns">
{{ if not .Project.IsHMN }} {{ if not .Project.IsHMN }}
<a class="project-logo" href="{{ currentprojecturl "/" }}"> <a class="project-logo" href="{{ projecturl "/" .Project }}">
<h1>{{ .Project.Name }}</h1> <h1>{{ .Project.Name }}</h1>
</a> </a>
{{ end }} {{ end }}
{{ if .Project.HasBlog }} {{ if .Project.HasBlog }}
<a href="{{ currentprojecturl "/blog" }}" class="blog">Blog</a> <a href="{{ projecturl "/blog" .Project }}" class="blog">Blog</a>
{{ end }} {{ end }}
{{ if .Project.HasForum }} {{ if .Project.HasForum }}
<a href="{{ currentprojecturl "/forum" }}" class="forums">Forums</a> <a href="{{ projecturl "/forums" .Project }}" class="forums">Forums</a>
{{ end }} {{ end }}
{{ if .Project.HasWiki }} {{ if .Project.HasWiki }}
<a href="{{ currentprojecturl "/wiki" }}" class="wiki">Wiki</a> <a href="{{ projecturl "/wiki" .Project }}" class="wiki">Wiki</a>
{{ end }} {{ end }}
{{ if .Project.HasLibrary }} {{ if .Project.HasLibrary }}
<a href="{{ currentprojecturl "/library" }}" class="library">Library</a> <a href="{{ projecturl "/library" .Project }}" class="library">Library</a>
{{ end }} {{ end }}
{{ if .Project.IsHMN }} {{ if .Project.IsHMN }}
<a href="{{ currentprojecturl "/manifesto" }}" class="misson">Mission</a> <a href="{{ projecturl "/manifesto" .Project }}" class="misson">Mission</a>
{{ end }} {{ end }}
{{/* {% if project.default_annotation_category %} */}} {{/* {% if project.default_annotation_category %} */}}
{{ if false }} {{ if false }}

View File

@ -4,7 +4,7 @@ This template is intended to display a single thread in the context of a forum,
It should be called with ThreadListItem. It should be called with ThreadListItem.
*/}} */}}
<div class="post-list-item flex items-center ph3 pv2 {{ if .Unread }}unread{{ else }}read{{ end }} {{ .Classes }}"> <div class="thread-list-item flex items-center ph3 pv2 {{ if .Unread }}unread{{ else }}read{{ end }} post-list-bg-odd {{ .Classes }}">
<img class="avatar-icon mr2" src="{{ .FirstUser.AvatarUrl }}"> <img class="avatar-icon mr2" src="{{ .FirstUser.AvatarUrl }}">
<div class="flex-grow-1 overflow-hidden"> <div class="flex-grow-1 overflow-hidden">
<div class="breadcrumbs"> <div class="breadcrumbs">
@ -23,7 +23,7 @@ It should be called with ThreadListItem.
</div> </div>
{{ end }} {{ end }}
</div> </div>
<div class="latestpost dn flex-ns flex-shrink-0 items-center w5 ml2"> <div class="latestpost dn flex-ns flex-shrink-0 items-center ml2">
<img class="avatar-icon mr2" src="{{ .LastUser.AvatarUrl }}"> <img class="avatar-icon mr2" src="{{ .LastUser.AvatarUrl }}">
<div> <div>
<div>Last post <span class="datetime">{{ relativedate .LastDate }}</span></div> <div>Last post <span class="datetime">{{ relativedate .LastDate }}</span></div>

View File

@ -63,6 +63,16 @@
<body class="{{ join " " .BodyClasses }}"> <body class="{{ join " " .BodyClasses }}">
<div class="content mw-site ph3-m ph4-l"> <div class="content mw-site ph3-m ph4-l">
{{ template "header.html" . }} {{ template "header.html" . }}
{{ with .Breadcrumbs }}
<div class="tc tl-ns ph2 ph0-ns pb2 pb0-ns">
{{ range $i, $e := . -}}
{{- if gt $i 0 -}}
<span class="ph2">&raquo;</span>
{{- end -}}
<a class="breadcrumb {{ if .Current }}current{{ end }}" href="{{ .Url }}">{{ .Name }}</a>
{{- end }}
</div>
{{ end }}
{{ block "content" . }}{{ end }} {{ block "content" . }}{{ end }}
{{ template "footer.html" . }} {{ template "footer.html" . }}
</div> </div>

View File

@ -42,6 +42,10 @@ a:hover, button:hover, .button:hover, input[type=button]:hover, input[type=submi
border: 2px solid var(--link-color); border: 2px solid var(--link-color);
} }
.post-list-bg-odd:nth-of-type(odd) {
background-color: {{ .PostListBgColor }};
}
/* /*
TODO: Manually apply sensible tachyons classes to the elements styled below, then delete TODO: Manually apply sensible tachyons classes to the elements styled below, then delete
all of this CSS. all of this CSS.

View File

@ -80,13 +80,6 @@ var HMNTemplateFuncs = template.FuncMap{
"color2css": func(color noire.Color) template.CSS { "color2css": func(color noire.Color) template.CSS {
return template.CSS(color.HTML()) return template.CSS(color.HTML())
}, },
"currentprojecturl": func(url string) string {
return hmnurl.Url(url, nil) // TODO: Use project subdomain
},
"currentprojecturlq": func(url string, query string) string {
absUrl := hmnurl.Url(url, nil)
return fmt.Sprintf("%s?%s", absUrl, query) // TODO: Use project subdomain
},
"darken": func(amount float64, color noire.Color) noire.Color { "darken": func(amount float64, color noire.Color) noire.Color {
return color.Shade(amount) return color.Shade(amount)
}, },

View File

@ -9,6 +9,7 @@ type BaseData struct {
BackgroundImage BackgroundImage BackgroundImage BackgroundImage
Theme string Theme string
BodyClasses []string BodyClasses []string
Breadcrumbs []Breadcrumb
Project Project Project Project
User *User User *User
@ -110,6 +111,7 @@ type ThreadListItem struct {
type Breadcrumb struct { type Breadcrumb struct {
Name, Url string Name, Url string
Current bool
} }
type Pagination struct { type Pagination struct {

View File

@ -2,12 +2,14 @@ package website
import ( import (
"context" "context"
"fmt"
"math" "math"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"git.handmade.network/hmn/hmn/src/hmnurl"
"git.handmade.network/hmn/hmn/src/templates" "git.handmade.network/hmn/hmn/src/templates"
"github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/pgx/v4/pgxpool"
@ -20,7 +22,9 @@ import (
type forumCategoryData struct { type forumCategoryData struct {
templates.BaseData templates.BaseData
Threads []templates.ThreadListItem CategoryUrl string
Threads []templates.ThreadListItem
Pagination templates.Pagination
} }
func ForumCategory(c *RequestContext) ResponseData { func ForumCategory(c *RequestContext) ResponseData {
@ -162,13 +166,37 @@ func ForumCategory(c *RequestContext) ResponseData {
//_ = itSubcats // TODO: Actually query subcategory post data //_ = itSubcats // TODO: Actually query subcategory post data
baseData := getBaseData(c) baseData := getBaseData(c)
baseData.Title = "yeet" baseData.Title = *c.CurrentProject.Name + " Forums"
baseData.Breadcrumbs = []templates.Breadcrumb{
{
Name: *c.CurrentProject.Name,
Url: hmnurl.ProjectUrl("/", nil, c.CurrentProject.Subdomain()),
},
{
Name: "Forums",
Url: categoryUrls[currentCatId],
Current: true,
},
}
var res ResponseData var res ResponseData
res.WriteTemplate("forum_category.html", forumCategoryData{ err = res.WriteTemplate("forum_category.html", forumCategoryData{
BaseData: baseData, BaseData: baseData,
Threads: threads, CategoryUrl: categoryUrls[currentCatId],
Threads: threads,
Pagination: templates.Pagination{
Current: page,
Total: numPages,
FirstUrl: categoryUrls[currentCatId],
LastUrl: fmt.Sprintf("%s/%d", categoryUrls[currentCatId], numPages),
NextUrl: fmt.Sprintf("%s/%d", categoryUrls[currentCatId], page+1),
PreviousUrl: fmt.Sprintf("%s/%d", categoryUrls[currentCatId], page-1),
},
}, c.Perf) }, c.Perf)
if err != nil {
panic(err)
}
return res return res
} }

View File

@ -64,7 +64,7 @@ func (rb *RouteBuilder) GET(regexStr string, h Handler) {
} }
func (rb *RouteBuilder) POST(regexStr string, h Handler) { func (rb *RouteBuilder) POST(regexStr string, h Handler) {
rb.Handle(http.MethodGet, regexStr, h) rb.Handle(http.MethodPost, regexStr, h)
} }
func (rb *RouteBuilder) StdHandler(regexStr string, h http.Handler) { func (rb *RouteBuilder) StdHandler(regexStr string, h http.Handler) {

View File

@ -17,6 +17,7 @@ import (
"git.handmade.network/hmn/hmn/src/perf" "git.handmade.network/hmn/hmn/src/perf"
"git.handmade.network/hmn/hmn/src/templates" "git.handmade.network/hmn/hmn/src/templates"
"github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/pgx/v4/pgxpool"
"github.com/teacat/noire"
) )
func NewWebsiteRoutes(conn *pgxpool.Pool, perfCollector *perf.PerfCollector) http.Handler { func NewWebsiteRoutes(conn *pgxpool.Pool, perfCollector *perf.PerfCollector) http.Handler {
@ -72,7 +73,7 @@ func NewWebsiteRoutes(conn *pgxpool.Pool, perfCollector *perf.PerfCollector) htt
}) })
mainRoutes.GET(`^/feed(/(?P<page>.+)?)?$`, Feed) mainRoutes.GET(`^/feed(/(?P<page>.+)?)?$`, Feed)
mainRoutes.GET(`^/(?P<cats>forums(/.+?)*)$`, ForumCategory) mainRoutes.GET(`^/(?P<cats>forums(/[a-zA-Z]+?)*)(/(?P<page>\d+))?$`, ForumCategory)
// mainRoutes.GET(`^/(?P<cats>forums(/cat)*)/t/(?P<threadid>\d+)/p/(?P<postid>\d+)$`, ForumPost) // mainRoutes.GET(`^/(?P<cats>forums(/cat)*)/t/(?P<threadid>\d+)/p/(?P<postid>\d+)$`, ForumPost)
mainRoutes.GET("^/assets/project.css$", ProjectCSS) mainRoutes.GET("^/assets/project.css$", ProjectCSS)
@ -96,7 +97,7 @@ func getBaseData(c *RequestContext) templates.BaseData {
return templates.BaseData{ return templates.BaseData{
Project: templates.ProjectToTemplate(c.CurrentProject), Project: templates.ProjectToTemplate(c.CurrentProject),
User: templateUser, User: templateUser,
Theme: "dark", Theme: "light",
} }
} }
@ -128,12 +129,28 @@ func ProjectCSS(c *RequestContext) ResponseData {
return ErrorResponse(http.StatusBadRequest, NewSafeError(nil, "You must provide a 'color' parameter.\n")) return ErrorResponse(http.StatusBadRequest, NewSafeError(nil, "You must provide a 'color' parameter.\n"))
} }
baseData := getBaseData(c)
bgColor := noire.NewHex(color)
h, s, l := bgColor.HSL()
if baseData.Theme == "dark" {
l = 15
} else {
l = 95
}
if s > 20 {
s = 20
}
bgColor = noire.NewHSL(h, s, l)
templateData := struct { templateData := struct {
Color string templates.BaseData
Theme string Color string
PostListBgColor string
}{ }{
Color: color, BaseData: baseData,
Theme: "dark", Color: color,
PostListBgColor: bgColor.HTML(),
} }
var res ResponseData var res ResponseData