+ {{ $newsPost := .NewsPost }}
{{ range $i, $col := .PostColumns }}
{{ if eq $i 0 }}
- Wow, a featured post!
- {{/* {% include "blog_index_thread_list_entry.html" with post=featured_post align_top=True %} */}}
+ {{ template "landing_page_featured_post" $newsPost}}
{{ end }}
{{ range $entry := $col }}
{{ $proj := $entry.Project }}
{{ $posts := $entry.Posts }}
-
{{/* TODO: Is this ID used for anything? */}}
-
+ {{ $c1 := hex2color $proj.Color1 }}
+
{{ $proj.Name }}
{{ with $entry.FeaturedPost }}
-
-
-
-
+ {{ template "landing_page_featured_post" . }}
{{ end }}
{{ range $post := $posts }}
{{ template "post_list_item.html" $post }}
{{ end }}
- {{/*
- {% with more=posts|length|add:-5|clamp_lower:0 %}
- {% if more > 0 %}
-
- {% endif %}
- {% endwith %}
- */}}
+
+
{{ end }}
@@ -94,43 +105,6 @@
{{ end }}
{{/*
-{{ define "extrahead" }}
-
-
-
-
-
-
-{{ end }}
-
{% block columns %}
{% include "showcase/js_templates.html" %}
{% include "timeline/js_templates.html" %}
@@ -288,4 +262,28 @@
{% endspaceless %}
{% endblock %}
-*/}}
\ No newline at end of file
+*/}}
+
+{{ define "landing_page_featured_post" }}
+{{/* Call this template with a LandingPageFeaturedPost. */}}
+
+
+
+
+{{ end }}
diff --git a/src/templates/src/layouts/base.html b/src/templates/src/layouts/base.html
index 149c6a2e..a36fe930 100644
--- a/src/templates/src/layouts/base.html
+++ b/src/templates/src/layouts/base.html
@@ -31,8 +31,8 @@
background-size: "{{ . }}";
{{ end }}
{{ else }}
- {{ $bgcolor := or .Project.Color1 "999999" }}
- background-color: #{{ eq .Theme "dark" | ternary (darken $bgcolor 0.6) (brighten $bgcolor 0.6) }};
+ {{ $bgcolor := or .Project.Color1 "999999" | hex2color }}
+ background-color: {{ eq .Theme "dark" | ternary (darken 0.6 $bgcolor) (brighten 0.6 $bgcolor) | color2css }};
background-image: url('data:image/png;base64,{{ eq .Theme "dark" | ternary $bgdark $bglight }}');
background-size: auto;
{{ end }}
diff --git a/src/templates/src/project.css b/src/templates/src/project.css
index 9748bc1a..e61c8167 100644
--- a/src/templates/src/project.css
+++ b/src/templates/src/project.css
@@ -1,43 +1,44 @@
-{{ $themeDim := eq .Theme "dark" | ternary (darken .Color 0.5) (brighten .Color 0.2) }}
-{{ $themeDimmer := eq .Theme "dark" | ternary (darken .Color 0.65) (brighten .Color 0.4) }}
-{{ $themeDimmest := eq .Theme "dark" | ternary (darken .Color 0.8) (brighten .Color 0.6) }}
+{{ $c := hex2color .Color }}
+{{ $themeDim := eq .Theme "dark" | ternary (lightness 0.35 $c) (lightness 0.75 $c) | color2css }}
+{{ $themeDimmer := eq .Theme "dark" | ternary (lightness 0.3 $c) (lightness 0.8 $c) | color2css }}
+{{ $themeDimmest := eq .Theme "dark" | ternary (lightness 0.2 $c) (lightness 0.85 $c) | color2css }}
-{{ $linkColor := eq .Theme "dark" | ternary (brighten .Color 0.1) (darken .Color 0.2) }}
-{{ $linkHoverColor := eq .Theme "dark" | ternary (brighten .Color 0.2) (darken .Color 0.1) }}
+{{ $linkColor := eq .Theme "dark" | ternary (lightness 0.55 $c) (lightness 0.35 $c) | color2css }}
+{{ $linkHoverColor := eq .Theme "dark" | ternary (lightness 0.65 $c) (lightness 0.45 $c) | color2css }}
:root {
- --theme-color: #{{ .Color }};
- --theme-color-dim: #{{ $themeDim }};
- --theme-color-dimmer: #{{ $themeDimmer }};
- --theme-color-dimmest: #{{ $themeDimmest }};
+ --theme-color: {{ $c | color2css }};
+ --theme-color-dim: {{ $themeDim }};
+ --theme-color-dimmer: {{ $themeDimmer }};
+ --theme-color-dimmest: {{ $themeDimmest }};
- --link-color: #{{ $linkColor }};
- --link-color-hover: #{{ $linkHoverColor }};
+ --link-color: {{ $linkColor }};
+ --link-color-hover: {{ $linkHoverColor }};
}
.accent {
- background-color: #{{ $themeDim }};
+ background-color: {{ $themeDim }};
background-color: var(--theme-dim);
}
.user-bar {
- border-bottom-color: #{{ $themeDim }};
+ border-bottom-color: {{ $themeDim }};
border-bottom-color: var(--theme-dim);
}
header .content-title .subtitle {
- border-top-color: #{{ $themeDim }};
+ border-top-color: {{ $themeDim }};
border-top-color: var(--theme-dim);
}
a, .thread:before, button, .button, input[type=button], input[type=submit] {
- color: #{{ $linkColor }};
+ color: {{ $linkColor }};
color: var(--link-color);
}
a:hover, button:hover, .button:hover, input[type=button]:hover, input[type=submit]:hover {
- color: #{{ $linkHoverColor }};
+ color: {{ $linkHoverColor }};
color: var(--link-hover-color);
}
.unread .avatar-icon {
- border: 2px solid #{{ $linkColor }};
+ border: 2px solid {{ $linkColor }};
border: 2px solid var(--link-color);
}
@@ -91,7 +92,7 @@ all of this CSS.
{% endif %} */
:root {
- --background-even-background: #{{ eq .Theme "dark" | ternary (darken .Color 0.8) (brighten .Color 0.9) }};
+ --background-even-background: {{ eq .Theme "dark" | ternary (lightness 0.15 $c) (lightness 0.95 $c) | color2css }};
}
/* Assets */
diff --git a/src/templates/templates.go b/src/templates/templates.go
index f5e68850..7dc1683b 100644
--- a/src/templates/templates.go
+++ b/src/templates/templates.go
@@ -67,15 +67,19 @@ func names(ts []*template.Template) []string {
}
var HMNTemplateFuncs = template.FuncMap{
- "brighten": func(hexColor string, amount float64) (string, error) {
- if len(hexColor) < 6 {
- return "", fmt.Errorf("couldn't brighten invalid hex color: %v", hexColor)
- }
- return noire.NewHex(hexColor).Tint(amount).Hex(), nil
+ "alpha": func(alpha float64, color noire.Color) noire.Color {
+ color.Alpha = alpha
+ return color
+ },
+ "brighten": func(amount float64, color noire.Color) noire.Color {
+ return color.Tint(amount)
},
"cachebust": func() string {
return cachebust
},
+ "color2css": func(color noire.Color) template.CSS {
+ return template.CSS(color.HTML())
+ },
"currentprojecturl": func(url string) string {
return hmnurl.Url(url, nil) // TODO: Use project subdomain
},
@@ -83,11 +87,18 @@ var HMNTemplateFuncs = template.FuncMap{
absUrl := hmnurl.Url(url, nil)
return fmt.Sprintf("%s?%s", absUrl, query) // TODO: Use project subdomain
},
- "darken": func(hexColor string, amount float64) (string, error) {
- if len(hexColor) < 6 {
- return "", fmt.Errorf("couldn't darken invalid hex color: %v", hexColor)
+ "darken": func(amount float64, color noire.Color) noire.Color {
+ return color.Shade(amount)
+ },
+ "hex2color": func(hex string) (noire.Color, error) {
+ if len(hex) < 6 {
+ return noire.Color{}, fmt.Errorf("hex color was invalid: %v", hex)
}
- return noire.NewHex(hexColor).Shade(amount).Hex(), nil
+ return noire.NewHex(hex), nil
+ },
+ "lightness": func(lightness float64, color noire.Color) noire.Color {
+ h, s, _, a := color.HSLA()
+ return noire.NewHSLA(h, s, lightness*100, a)
},
"projecturl": func(url string, proj interface{}) string {
return hmnurl.ProjectUrl(url, nil, getProjectSubdomain(proj))
diff --git a/src/website/landing.go b/src/website/landing.go
index ce2029ee..6c13c09e 100644
--- a/src/website/landing.go
+++ b/src/website/landing.go
@@ -1,6 +1,7 @@
package website
import (
+ "html/template"
"net/http"
"time"
@@ -13,6 +14,7 @@ import (
type LandingTemplateData struct {
templates.BaseData
+ NewsPost LandingPageFeaturedPost
PostColumns [][]LandingPageProject
ShowcaseTimelineJson string
}
@@ -29,7 +31,7 @@ type LandingPageFeaturedPost struct {
User templates.User
Date time.Time
Unread bool
- Content string
+ Content template.HTML
}
func Index(c *RequestContext) ResponseData {
@@ -67,7 +69,7 @@ func Index(c *RequestContext) ResponseData {
for _, projRow := range allProjects {
proj := projRow.(*models.Project)
- type ProjectPost struct {
+ type projectPostQuery struct {
Post models.Post `db:"post"`
Thread models.Thread `db:"thread"`
Cat models.Category `db:"cat"`
@@ -75,8 +77,7 @@ func Index(c *RequestContext) ResponseData {
ThreadLastReadTime *time.Time `db:"tlri.lastread"`
CatLastReadTime *time.Time `db:"clri.lastread"`
}
-
- projectPostIter, err := db.Query(c.Context(), c.Conn, ProjectPost{},
+ projectPostIter, err := db.Query(c.Context(), c.Conn, projectPostQuery{},
`
SELECT $columns
FROM
@@ -116,7 +117,7 @@ func Index(c *RequestContext) ResponseData {
}
for _, projectPostRow := range projectPosts {
- projectPost := projectPostRow.(*ProjectPost)
+ projectPost := projectPostRow.(*projectPostQuery)
hasRead := false
if projectPost.ThreadLastReadTime != nil && projectPost.ThreadLastReadTime.After(projectPost.Post.PostDate) {
@@ -148,20 +149,18 @@ func Index(c *RequestContext) ResponseData {
}
content := contentResult.(*featuredContentResult).Content
- // c.Logger.Debug().Str("content", content).Msg("")
-
landingPageProject.FeaturedPost = &LandingPageFeaturedPost{
Title: projectPost.Thread.Title,
- Url: templates.PostUrl(projectPost.Post, projectPost.Cat.Kind, proj.Subdomain()), // TODO
+ Url: templates.PostUrl(projectPost.Post, projectPost.Cat.Kind, proj.Subdomain()),
User: templates.UserToTemplate(&projectPost.User),
Date: projectPost.Post.PostDate,
Unread: !hasRead,
- Content: content,
+ Content: template.HTML(content),
}
} else {
landingPageProject.Posts = append(landingPageProject.Posts, templates.PostListItem{
Title: projectPost.Thread.Title,
- Url: templates.PostUrl(projectPost.Post, projectPost.Cat.Kind, proj.Subdomain()), // TODO
+ Url: templates.PostUrl(projectPost.Post, projectPost.Cat.Kind, proj.Subdomain()),
User: templates.UserToTemplate(&projectPost.User),
Date: projectPost.Post.PostDate,
Unread: !hasRead,
@@ -230,12 +229,51 @@ func Index(c *RequestContext) ResponseData {
}
}
+ type newsPostQuery struct {
+ Post models.Post `db:"post"`
+ PostVersion models.PostVersion `db:"ver"`
+ Thread models.Thread `db:"thread"`
+ User models.User `db:"auth_user"`
+ }
+ newsPostRow, err := db.QueryOne(c.Context(), c.Conn, newsPostQuery{},
+ `
+ SELECT $columns
+ FROM
+ handmade_post AS post
+ JOIN handmade_thread AS thread ON post.thread_id = thread.id
+ JOIN handmade_category AS cat ON thread.category_id = cat.id
+ JOIN auth_user ON post.author_id = auth_user.id
+ JOIN handmade_postversion AS ver ON post.current_id = ver.id
+ WHERE
+ cat.project_id = $1
+ AND cat.kind = $2
+ AND post.id = thread.first_id
+ AND thread.moderated = 0
+ ORDER BY post.postdate DESC
+ LIMIT 1
+ `,
+ models.HMNProjectID,
+ models.CatTypeBlog,
+ )
+ if err != nil {
+ return ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch news post"))
+ }
+ newsPostResult := newsPostRow.(*newsPostQuery)
+
baseData := getBaseData(c)
baseData.BodyClasses = append(baseData.BodyClasses, "hmdev", "landing") // TODO: Is "hmdev" necessary any more?
var res ResponseData
err = res.WriteTemplate("index.html", LandingTemplateData{
- BaseData: getBaseData(c),
+ BaseData: baseData,
+ NewsPost: LandingPageFeaturedPost{
+ Title: newsPostResult.Thread.Title,
+ Url: templates.PostUrl(newsPostResult.Post, models.CatTypeBlog, ""),
+ User: templates.UserToTemplate(&newsPostResult.User),
+ Date: newsPostResult.Post.PostDate,
+ Unread: true, // TODO
+ Content: template.HTML(newsPostResult.PostVersion.TextParsed),
+ },
PostColumns: cols,
})
if err != nil {