Photos page

This commit is contained in:
Jan-Lukas Else 2020-09-21 18:03:05 +02:00
parent f5cca985bd
commit 1c8da99620
8 changed files with 151 additions and 39 deletions

View File

@ -49,6 +49,8 @@ type configBlog struct {
Taxonomies []*taxonomy `mapstructure:"taxonomies"`
// Menus
Menus map[string]*menu `mapstructure:"menus"`
// Photos
Photos *photos `mapstructure:"photos"`
}
type section struct {
@ -72,6 +74,14 @@ type menuItem struct {
Link string `mapstructure:"link"`
}
type photos struct {
Enabled bool `mapstructure:"enabled"`
Parameter string `mapstructure:"parameter"`
Path string `mapstructure:"path"`
Title string `mapstructure:"title"`
Description string `mapstructure:"description"`
}
type configUser struct {
Nick string `mapstructure:"nick"`
Name string `mapstructure:"name"`
@ -119,6 +129,11 @@ func initConfig() error {
viper.SetDefault("blog.sections", []*section{{Name: "posts", Title: "Posts", Description: "**Posts** on this blog"}})
viper.SetDefault("blog.taxonomies", []*taxonomy{{Name: "tags", Title: "Tags", Description: "**Tags** on this blog"}})
viper.SetDefault("blog.menus", map[string]*menu{"main": {Items: []*menuItem{{Title: "Home", Link: "/"}, {Title: "Post", Link: "Posts"}}}})
viper.SetDefault("blog.photos.enabled", true)
viper.SetDefault("blog.photos.parameter", "images")
viper.SetDefault("blog.photos.path", "/photos")
viper.SetDefault("blog.photos.title", "Photos")
viper.SetDefault("blog.photos.description", "Photos on this blog")
viper.SetDefault("user.nick", "admin")
viper.SetDefault("user.name", "Admin")
viper.SetDefault("user.password", "secret")

View File

@ -30,6 +30,12 @@ blog:
link: /
- title: Posts
link: /posts
photos:
enable: true
parameter: images
path: /photos
title: Photos
description: "Photos on this blog"
user:
nick: admin
name: Admin

View File

@ -133,6 +133,11 @@ func buildHandler() (http.Handler, error) {
}
}
if appConfig.Blog.Photos.Enabled {
r.With(cacheMiddleware, minifier.Middleware).Get(appConfig.Blog.Photos.Path, servePhotos(appConfig.Blog.Photos.Path))
r.With(cacheMiddleware, minifier.Middleware).Get(appConfig.Blog.Photos.Path+paginationPath, servePhotos(appConfig.Blog.Photos.Path))
}
// Blog
rootPath := "/"
blogPath := "/blog"

View File

@ -74,11 +74,18 @@ func (p *postPaginationAdapter) Slice(offset, length int, data interface{}) erro
}
func serveHome(path string, ft feedType) func(w http.ResponseWriter, r *http.Request) {
return serveIndex(path, nil, nil, "", ft)
return serveIndex(&indexConfig{
path: path,
feed: ft,
})
}
func serveSection(path string, section *section, ft feedType) func(w http.ResponseWriter, r *http.Request) {
return serveIndex(path, section, nil, "", ft)
return serveIndex(&indexConfig{
path: path,
section: section,
feed: ft,
})
}
func serveTaxonomy(tax *taxonomy) func(w http.ResponseWriter, r *http.Request) {
@ -99,21 +106,45 @@ func serveTaxonomy(tax *taxonomy) func(w http.ResponseWriter, r *http.Request) {
}
func serveTaxonomyValue(path string, tax *taxonomy, value string, ft feedType) func(w http.ResponseWriter, r *http.Request) {
return serveIndex(path, nil, tax, value, ft)
return serveIndex(&indexConfig{
path: path,
tax: tax,
taxValue: value,
feed: ft,
})
}
func serveIndex(path string, sec *section, tax *taxonomy, taxonomyValue string, ft feedType) func(w http.ResponseWriter, r *http.Request) {
func servePhotos(path string) func(w http.ResponseWriter, r *http.Request) {
return serveIndex(&indexConfig{
path: path,
onlyWithParameter: appConfig.Blog.Photos.Parameter,
template: templatePhotos,
})
}
type indexConfig struct {
path string
section *section
tax *taxonomy
taxValue string
feed feedType
onlyWithParameter string
template string
}
func serveIndex(ic *indexConfig) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
pageNoString := chi.URLParam(r, "page")
pageNo, _ := strconv.Atoi(pageNoString)
sections := appConfig.Blog.Sections
if sec != nil {
sections = []*section{sec}
if ic.section != nil {
sections = []*section{ic.section}
}
p := paginator.New(&postPaginationAdapter{context: r.Context(), config: &postsRequestConfig{
sections: sections,
taxonomy: tax,
taxonomyValue: taxonomyValue,
sections: sections,
taxonomy: ic.tax,
taxonomyValue: ic.taxValue,
onlyWithParameter: ic.onlyWithParameter,
}}, appConfig.Blog.Pagination)
p.SetPage(pageNo)
var posts []*Post
@ -124,15 +155,15 @@ func serveIndex(path string, sec *section, tax *taxonomy, taxonomyValue string,
}
// Meta
var title, description string
if tax != nil {
title = fmt.Sprintf("%s: %s", tax.Title, taxonomyValue)
} else if sec != nil {
title = sec.Title
description = sec.Description
if ic.tax != nil {
title = fmt.Sprintf("%s: %s", ic.tax.Title, ic.taxValue)
} else if ic.section != nil {
title = ic.section.Title
description = ic.section.Description
}
// Check if feed
if ft != NONE {
generateFeed(ft, w, r, posts, title, description)
if ic.feed != NONE {
generateFeed(ic.feed, w, r, posts, title, description)
return
}
// Navigation
@ -144,15 +175,19 @@ func serveIndex(path string, sec *section, tax *taxonomy, taxonomyValue string,
if err == paginator.ErrNoNextPage {
nextPage = p.Page()
}
render(w, templateIndex, &indexTemplateData{
template := ic.template
if len(template) == 0 {
template = templateIndex
}
render(w, template, &indexTemplateData{
Title: title,
Description: description,
Posts: posts,
HasPrev: p.HasPrev(),
HasNext: p.HasNext(),
First: path,
Prev: fmt.Sprintf("%s/page/%d", path, prevPage),
Next: fmt.Sprintf("%s/page/%d", path, nextPage),
First: ic.path,
Prev: fmt.Sprintf("%s/page/%d", ic.path, prevPage),
Next: fmt.Sprintf("%s/page/%d", ic.path, nextPage),
})
}
}
@ -168,12 +203,13 @@ func getPost(context context.Context, path string) (*Post, error) {
}
type postsRequestConfig struct {
path string
limit int
offset int
sections []*section
taxonomy *taxonomy
taxonomyValue string
path string
limit int
offset int
sections []*section
taxonomy *taxonomy
taxonomyValue string
onlyWithParameter string
}
func getPosts(context context.Context, config *postsRequestConfig) (posts []*Post, err error) {
@ -181,6 +217,9 @@ func getPosts(context context.Context, config *postsRequestConfig) (posts []*Pos
var rows *sql.Rows
defaultSelection := "select p.path, coalesce(content, ''), coalesce(published, ''), coalesce(updated, ''), coalesce(parameter, ''), coalesce(value, '') "
postsTable := "posts"
if config.onlyWithParameter != "" {
postsTable = "(select distinct p.* from " + postsTable + " p left outer join post_parameters pp on p.path = pp.path where pp.parameter = '" + config.onlyWithParameter + "' and length(coalesce(pp.value, '')) > 1)"
}
if config.taxonomy != nil && len(config.taxonomyValue) > 0 {
postsTable = "(select distinct p.* from " + postsTable + " p left outer join post_parameters pp on p.path = pp.path where pp.parameter = '" + config.taxonomy.Name + "' and lower(pp.value) = lower('" + config.taxonomyValue + "'))"
}

View File

@ -22,6 +22,7 @@ const templateError = "error"
const templateRedirect = "redirect"
const templateIndex = "index"
const templateTaxonomy = "taxonomy"
const templatePhotos = "photos"
var templates map[string]*template.Template
var templateFunctions template.FuncMap

View File

@ -1,17 +1,21 @@
{{ define "title" }}
<title>{{ blog.Title }}</title>
<link rel="alternate"
type="application/rss+xml"
title="RSS"
href="{{ .First }}.rss"/>
<link rel="alternate"
type="application/atom+xml"
title="Atom"
href="{{ .First }}.atom"/>
<link rel="alternate"
type="application/feed+json"
title="JSON Feed"
href="{{ .First }}.json"/>
{{ if .Title }}
<title>{{ .Title }} - {{ blog.Title }}</title>
{{ else }}
<title>{{ blog.Title }}</title>
{{ end }}
<link rel="alternate"
type="application/rss+xml"
title="RSS"
href="{{ .First }}.rss"/>
<link rel="alternate"
type="application/atom+xml"
title="Atom"
href="{{ .First }}.atom"/>
<link rel="alternate"
type="application/feed+json"
title="JSON Feed"
href="{{ .First }}.json"/>
{{ end }}
{{ define "main" }}

30
templates/photos.gohtml Normal file
View File

@ -0,0 +1,30 @@
{{ define "title" }}
{{ if blog.Photos.Title }}
<title>{{ blog.Photos.Title }} - {{ blog.Title }}</title>
{{ else }}
<title>{{ blog.Title }}</title>
{{ end }}
{{ end }}
{{ define "main" }}
<main>
{{ with blog.Photos.Title }}<h1>{{ . }}</h1>{{ end }}
{{ with blog.Photos.Description }}{{ md . }}{{ end }}
{{ if (or blog.Photos.Title blog.Photos.Description) }}
<hr>
{{ end }}
{{ range $i, $post := .Posts }}
{{ include "photosummary" . }}
{{ end }}
{{ if .HasPrev }}
<p><a href="{{ .Prev }}">Prev</a></p>
{{ end }}
{{ if .HasNext }}
<p><a href="{{ .Next }}">Next</a></p>
{{ end }}
</main>
{{ end }}
{{ define "photos" }}
{{ template "base" . }}
{{ end }}

View File

@ -0,0 +1,12 @@
{{ define "photosummary" }}
<article>
{{ with p . "title" }}<h2>{{ . }}</h2>{{ end }}
{{ with .Published }}<p>{{ dateformat . "02. Jan 2006" }}</p>{{ end }}
{{ range $i, $photo := ( ps . blog.Photos.Parameter ) }}
{{ md ( printf "![](%s)" $photo ) }}
{{ end }}
<p>{{ summary . }}</p>
<a href="{{ .Path }}">View</a>
</article>
<hr>
{{ end }}