mirror of https://github.com/jlelse/GoBlog
Photos page
This commit is contained in:
parent
f5cca985bd
commit
1c8da99620
15
config.go
15
config.go
|
@ -49,6 +49,8 @@ type configBlog struct {
|
||||||
Taxonomies []*taxonomy `mapstructure:"taxonomies"`
|
Taxonomies []*taxonomy `mapstructure:"taxonomies"`
|
||||||
// Menus
|
// Menus
|
||||||
Menus map[string]*menu `mapstructure:"menus"`
|
Menus map[string]*menu `mapstructure:"menus"`
|
||||||
|
// Photos
|
||||||
|
Photos *photos `mapstructure:"photos"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type section struct {
|
type section struct {
|
||||||
|
@ -72,6 +74,14 @@ type menuItem struct {
|
||||||
Link string `mapstructure:"link"`
|
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 {
|
type configUser struct {
|
||||||
Nick string `mapstructure:"nick"`
|
Nick string `mapstructure:"nick"`
|
||||||
Name string `mapstructure:"name"`
|
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.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.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.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.nick", "admin")
|
||||||
viper.SetDefault("user.name", "Admin")
|
viper.SetDefault("user.name", "Admin")
|
||||||
viper.SetDefault("user.password", "secret")
|
viper.SetDefault("user.password", "secret")
|
||||||
|
|
|
@ -30,6 +30,12 @@ blog:
|
||||||
link: /
|
link: /
|
||||||
- title: Posts
|
- title: Posts
|
||||||
link: /posts
|
link: /posts
|
||||||
|
photos:
|
||||||
|
enable: true
|
||||||
|
parameter: images
|
||||||
|
path: /photos
|
||||||
|
title: Photos
|
||||||
|
description: "Photos on this blog"
|
||||||
user:
|
user:
|
||||||
nick: admin
|
nick: admin
|
||||||
name: Admin
|
name: Admin
|
||||||
|
|
5
http.go
5
http.go
|
@ -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
|
// Blog
|
||||||
rootPath := "/"
|
rootPath := "/"
|
||||||
blogPath := "/blog"
|
blogPath := "/blog"
|
||||||
|
|
91
posts.go
91
posts.go
|
@ -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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
pageNoString := chi.URLParam(r, "page")
|
pageNoString := chi.URLParam(r, "page")
|
||||||
pageNo, _ := strconv.Atoi(pageNoString)
|
pageNo, _ := strconv.Atoi(pageNoString)
|
||||||
sections := appConfig.Blog.Sections
|
sections := appConfig.Blog.Sections
|
||||||
if sec != nil {
|
if ic.section != nil {
|
||||||
sections = []*section{sec}
|
sections = []*section{ic.section}
|
||||||
}
|
}
|
||||||
p := paginator.New(&postPaginationAdapter{context: r.Context(), config: &postsRequestConfig{
|
p := paginator.New(&postPaginationAdapter{context: r.Context(), config: &postsRequestConfig{
|
||||||
sections: sections,
|
sections: sections,
|
||||||
taxonomy: tax,
|
taxonomy: ic.tax,
|
||||||
taxonomyValue: taxonomyValue,
|
taxonomyValue: ic.taxValue,
|
||||||
|
onlyWithParameter: ic.onlyWithParameter,
|
||||||
}}, appConfig.Blog.Pagination)
|
}}, appConfig.Blog.Pagination)
|
||||||
p.SetPage(pageNo)
|
p.SetPage(pageNo)
|
||||||
var posts []*Post
|
var posts []*Post
|
||||||
|
@ -124,15 +155,15 @@ func serveIndex(path string, sec *section, tax *taxonomy, taxonomyValue string,
|
||||||
}
|
}
|
||||||
// Meta
|
// Meta
|
||||||
var title, description string
|
var title, description string
|
||||||
if tax != nil {
|
if ic.tax != nil {
|
||||||
title = fmt.Sprintf("%s: %s", tax.Title, taxonomyValue)
|
title = fmt.Sprintf("%s: %s", ic.tax.Title, ic.taxValue)
|
||||||
} else if sec != nil {
|
} else if ic.section != nil {
|
||||||
title = sec.Title
|
title = ic.section.Title
|
||||||
description = sec.Description
|
description = ic.section.Description
|
||||||
}
|
}
|
||||||
// Check if feed
|
// Check if feed
|
||||||
if ft != NONE {
|
if ic.feed != NONE {
|
||||||
generateFeed(ft, w, r, posts, title, description)
|
generateFeed(ic.feed, w, r, posts, title, description)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Navigation
|
// Navigation
|
||||||
|
@ -144,15 +175,19 @@ func serveIndex(path string, sec *section, tax *taxonomy, taxonomyValue string,
|
||||||
if err == paginator.ErrNoNextPage {
|
if err == paginator.ErrNoNextPage {
|
||||||
nextPage = p.Page()
|
nextPage = p.Page()
|
||||||
}
|
}
|
||||||
render(w, templateIndex, &indexTemplateData{
|
template := ic.template
|
||||||
|
if len(template) == 0 {
|
||||||
|
template = templateIndex
|
||||||
|
}
|
||||||
|
render(w, template, &indexTemplateData{
|
||||||
Title: title,
|
Title: title,
|
||||||
Description: description,
|
Description: description,
|
||||||
Posts: posts,
|
Posts: posts,
|
||||||
HasPrev: p.HasPrev(),
|
HasPrev: p.HasPrev(),
|
||||||
HasNext: p.HasNext(),
|
HasNext: p.HasNext(),
|
||||||
First: path,
|
First: ic.path,
|
||||||
Prev: fmt.Sprintf("%s/page/%d", path, prevPage),
|
Prev: fmt.Sprintf("%s/page/%d", ic.path, prevPage),
|
||||||
Next: fmt.Sprintf("%s/page/%d", path, nextPage),
|
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 {
|
type postsRequestConfig struct {
|
||||||
path string
|
path string
|
||||||
limit int
|
limit int
|
||||||
offset int
|
offset int
|
||||||
sections []*section
|
sections []*section
|
||||||
taxonomy *taxonomy
|
taxonomy *taxonomy
|
||||||
taxonomyValue string
|
taxonomyValue string
|
||||||
|
onlyWithParameter string
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPosts(context context.Context, config *postsRequestConfig) (posts []*Post, err error) {
|
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
|
var rows *sql.Rows
|
||||||
defaultSelection := "select p.path, coalesce(content, ''), coalesce(published, ''), coalesce(updated, ''), coalesce(parameter, ''), coalesce(value, '') "
|
defaultSelection := "select p.path, coalesce(content, ''), coalesce(published, ''), coalesce(updated, ''), coalesce(parameter, ''), coalesce(value, '') "
|
||||||
postsTable := "posts"
|
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 {
|
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 + "'))"
|
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 + "'))"
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ const templateError = "error"
|
||||||
const templateRedirect = "redirect"
|
const templateRedirect = "redirect"
|
||||||
const templateIndex = "index"
|
const templateIndex = "index"
|
||||||
const templateTaxonomy = "taxonomy"
|
const templateTaxonomy = "taxonomy"
|
||||||
|
const templatePhotos = "photos"
|
||||||
|
|
||||||
var templates map[string]*template.Template
|
var templates map[string]*template.Template
|
||||||
var templateFunctions template.FuncMap
|
var templateFunctions template.FuncMap
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
{{ define "title" }}
|
{{ define "title" }}
|
||||||
<title>{{ blog.Title }}</title>
|
{{ if .Title }}
|
||||||
<link rel="alternate"
|
<title>{{ .Title }} - {{ blog.Title }}</title>
|
||||||
type="application/rss+xml"
|
{{ else }}
|
||||||
title="RSS"
|
<title>{{ blog.Title }}</title>
|
||||||
href="{{ .First }}.rss"/>
|
{{ end }}
|
||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="application/atom+xml"
|
type="application/rss+xml"
|
||||||
title="Atom"
|
title="RSS"
|
||||||
href="{{ .First }}.atom"/>
|
href="{{ .First }}.rss"/>
|
||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="application/feed+json"
|
type="application/atom+xml"
|
||||||
title="JSON Feed"
|
title="Atom"
|
||||||
href="{{ .First }}.json"/>
|
href="{{ .First }}.atom"/>
|
||||||
|
<link rel="alternate"
|
||||||
|
type="application/feed+json"
|
||||||
|
title="JSON Feed"
|
||||||
|
href="{{ .First }}.json"/>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ define "main" }}
|
{{ define "main" }}
|
||||||
|
|
|
@ -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 }}
|
|
@ -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 }}
|
Loading…
Reference in New Issue