Multitag frontend update, bug fixes
* Checking the box to reset a post's UpdatedAt to CreatedAt now actually does so (removes the "updated at" label from front-end) * Tagged Posts index now has better header formatting when multi-tags are in use. * No longer "Tagged as: hello,world,-mars" * Now is titled "Tagged Posts" and includes the lists of Tags and Not formatted nicely with clickable links. * Fixes the "Read more..." link always appearing in HTML-type blog posts even when they didn't use the `<snip>` tag.master
parent
b57dfa9e64
commit
211b7d8318
|
@ -7,7 +7,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.kirsle.net/apps/gophertype/pkg/authentication"
|
"git.kirsle.net/apps/gophertype/pkg/authentication"
|
||||||
"git.kirsle.net/apps/gophertype/pkg/glue"
|
"git.kirsle.net/apps/gophertype/pkg/glue"
|
||||||
|
@ -91,6 +90,11 @@ func BlogIndex(privacy string, tagged bool) http.HandlerFunc {
|
||||||
var (
|
var (
|
||||||
v = responses.NewTemplateVars(w, r)
|
v = responses.NewTemplateVars(w, r)
|
||||||
tagName string
|
tagName string
|
||||||
|
|
||||||
|
// Multitag values.
|
||||||
|
isMultitag bool
|
||||||
|
include []string
|
||||||
|
exclude []string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tagged view?
|
// Tagged view?
|
||||||
|
@ -102,7 +106,17 @@ func BlogIndex(privacy string, tagged bool) http.HandlerFunc {
|
||||||
// Page title to use.
|
// Page title to use.
|
||||||
var title = "Blog"
|
var title = "Blog"
|
||||||
if tagged {
|
if tagged {
|
||||||
title = "Tagged as: " + tagName
|
// Check for use of multi-tags.
|
||||||
|
if strings.Contains(tagName, ",") {
|
||||||
|
title = "Tagged Posts"
|
||||||
|
if inc, exc, err := models.ParseMultitag(tagName); err == nil {
|
||||||
|
isMultitag = true
|
||||||
|
include = inc
|
||||||
|
exclude = exc
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title = "Tagged as: " + tagName
|
||||||
|
}
|
||||||
} else if privacy == models.Draft {
|
} else if privacy == models.Draft {
|
||||||
title = "Drafts"
|
title = "Drafts"
|
||||||
} else if privacy == models.Unlisted {
|
} else if privacy == models.Unlisted {
|
||||||
|
@ -113,6 +127,15 @@ func BlogIndex(privacy string, tagged bool) http.HandlerFunc {
|
||||||
|
|
||||||
v.V["title"] = title
|
v.V["title"] = title
|
||||||
v.V["tag"] = tagName
|
v.V["tag"] = tagName
|
||||||
|
v.V["Multitag"] = struct {
|
||||||
|
Is bool
|
||||||
|
Include []string
|
||||||
|
Exclude []string
|
||||||
|
}{
|
||||||
|
isMultitag,
|
||||||
|
include,
|
||||||
|
exclude,
|
||||||
|
}
|
||||||
v.V["privacy"] = privacy
|
v.V["privacy"] = privacy
|
||||||
responses.RenderTemplate(w, r, "_builtin/blog/index.gohtml", v)
|
responses.RenderTemplate(w, r, "_builtin/blog/index.gohtml", v)
|
||||||
}
|
}
|
||||||
|
@ -257,13 +280,13 @@ func EditPost(w http.ResponseWriter, r *http.Request) {
|
||||||
post.AuthorID = author.ID
|
post.AuthorID = author.ID
|
||||||
|
|
||||||
// When editing, allow to not touch the Last Updated time.
|
// When editing, allow to not touch the Last Updated time.
|
||||||
if !isNew && form.GetBool("no-update") == true {
|
var resetUpdated bool = !isNew && form.GetBool("no-update") == true
|
||||||
post.UpdatedAt = post.CreatedAt
|
|
||||||
} else {
|
|
||||||
post.UpdatedAt = time.Now().UTC()
|
|
||||||
}
|
|
||||||
|
|
||||||
err := post.Save()
|
err := post.Save()
|
||||||
|
if resetUpdated {
|
||||||
|
post.SetUpdated(post.CreatedAt)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.Error = err
|
v.Error = err
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -81,7 +81,7 @@ func (m commentMan) LoadByDeleteToken(token string) (Comment, error) {
|
||||||
// GetIndex returns the index page of blog posts.
|
// GetIndex returns the index page of blog posts.
|
||||||
func (m commentMan) GetThread(thread string) ([]Comment, error) {
|
func (m commentMan) GetThread(thread string) ([]Comment, error) {
|
||||||
var coms []Comment
|
var coms []Comment
|
||||||
r := DB.Debug().Preload("User").
|
r := DB.Preload("User").
|
||||||
Where("thread = ?", thread).
|
Where("thread = ?", thread).
|
||||||
Order("created_at asc").
|
Order("created_at asc").
|
||||||
Find(&coms)
|
Find(&coms)
|
||||||
|
@ -102,7 +102,7 @@ func (m commentMan) GetRecent(page int, perPage int) (PagedComments, error) {
|
||||||
pc.PerPage = 20
|
pc.PerPage = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
query := DB.Debug().Preload("User").Preload("Post").
|
query := DB.Preload("User").Preload("Post").
|
||||||
Order("created_at desc")
|
Order("created_at desc")
|
||||||
|
|
||||||
// Count the total number of rows.
|
// Count the total number of rows.
|
||||||
|
@ -148,12 +148,12 @@ func (m commentMan) GetSubscribers(thread string) ([]string, error) {
|
||||||
func (m commentMan) UnsubscribeThread(thread string, email string) error {
|
func (m commentMan) UnsubscribeThread(thread string, email string) error {
|
||||||
// Verify the thread is valid.
|
// Verify the thread is valid.
|
||||||
var count int
|
var count int
|
||||||
DB.Debug().Model(&Comment{}).Where("thread=?", thread).Count(&count)
|
DB.Model(&Comment{}).Where("thread=?", thread).Count(&count)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return errors.New("invalid comment thread")
|
return errors.New("invalid comment thread")
|
||||||
}
|
}
|
||||||
|
|
||||||
r := DB.Debug().Table("comments").Where("thread=? AND subscribe=?", thread, true).Updates(map[string]interface{}{
|
r := DB.Table("comments").Where("thread=? AND subscribe=?", thread, true).Updates(map[string]interface{}{
|
||||||
"subscribe": false,
|
"subscribe": false,
|
||||||
})
|
})
|
||||||
return r.Error
|
return r.Error
|
||||||
|
@ -161,7 +161,7 @@ func (m commentMan) UnsubscribeThread(thread string, email string) error {
|
||||||
|
|
||||||
// UnsubscribeFromAll remove's an email subscription for ALL comment threads.
|
// UnsubscribeFromAll remove's an email subscription for ALL comment threads.
|
||||||
func (m commentMan) UnsubscribeFromAll(email string) error {
|
func (m commentMan) UnsubscribeFromAll(email string) error {
|
||||||
r := DB.Debug().Table("comments").Where("email=?", email).Updates(map[string]interface{}{
|
r := DB.Table("comments").Where("email=?", email).Updates(map[string]interface{}{
|
||||||
"subscribe": false,
|
"subscribe": false,
|
||||||
})
|
})
|
||||||
return r.Error
|
return r.Error
|
||||||
|
|
|
@ -90,7 +90,7 @@ func (m postMan) LoadFragment(fragment string) (Post, error) {
|
||||||
func (m postMan) LoadRandom(privacy string) (Post, error) {
|
func (m postMan) LoadRandom(privacy string) (Post, error) {
|
||||||
// Find all the post IDs.
|
// Find all the post IDs.
|
||||||
var pp []Post
|
var pp []Post
|
||||||
r := DB.Debug().Select("id").Where("privacy = ?", privacy).Find(&pp)
|
r := DB.Select("id").Where("privacy = ?", privacy).Find(&pp)
|
||||||
if r.Error != nil || len(pp) == 0 {
|
if r.Error != nil || len(pp) == 0 {
|
||||||
return Post{}, r.Error
|
return Post{}, r.Error
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,9 @@ func (p Post) PreviewHTML() template.HTML {
|
||||||
return template.HTML(markdown.RenderTrustedMarkdown(body))
|
return template.HTML(markdown.RenderTrustedMarkdown(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
body += fmt.Sprintf(`<p><a href="/%s">Read more...</a></p>`, p.Fragment)
|
if hasMore {
|
||||||
|
body += fmt.Sprintf(`<p><a href="/%s">Read more...</a></p>`, p.Fragment)
|
||||||
|
}
|
||||||
return template.HTML(body)
|
return template.HTML(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,6 +468,14 @@ func (p *Post) Save() error {
|
||||||
return DB.Save(&p).Error
|
return DB.Save(&p).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUpdated force sets the updated time of a post, i.e. to reset it to original.
|
||||||
|
func (p Post) SetUpdated(dt time.Time) error {
|
||||||
|
r := DB.Table("posts").Where("id = ?", p.ID).Updates(map[string]interface{}{
|
||||||
|
"updated_at": dt,
|
||||||
|
})
|
||||||
|
return r.Error
|
||||||
|
}
|
||||||
|
|
||||||
// ParseForm populates a Post from an HTTP form.
|
// ParseForm populates a Post from an HTTP form.
|
||||||
func (p *Post) ParseForm(form *forms.Data) {
|
func (p *Post) ParseForm(form *forms.Data) {
|
||||||
p.Title = form.Get("title")
|
p.Title = form.Get("title")
|
||||||
|
|
|
@ -3,6 +3,30 @@
|
||||||
|
|
||||||
<h1>{{ or .V.title "Blog" }}</h1>
|
<h1>{{ or .V.title "Blog" }}</h1>
|
||||||
|
|
||||||
|
{{ if .V.Multitag.Is }}
|
||||||
|
<div class="alert alert-secondary">
|
||||||
|
<small><em>
|
||||||
|
{{ if .V.Multitag.Include }}
|
||||||
|
<span class="mr-2">
|
||||||
|
<strong>Tags:</strong>
|
||||||
|
{{ range $tag := .V.Multitag.Include }}
|
||||||
|
<a href="/tagged/{{ $tag }}" class="ml-2">#{{ $tag }}</a>
|
||||||
|
{{ end }}
|
||||||
|
</span>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .V.Multitag.Exclude }}
|
||||||
|
<span class="mr-2">
|
||||||
|
<strong>Not:</strong>
|
||||||
|
{{ range $tag := .V.Multitag.Exclude }}
|
||||||
|
<a href="/tagged/{{ $tag }}" class="ml-2">#{{ $tag }}</a>
|
||||||
|
{{ end }}
|
||||||
|
</span>
|
||||||
|
{{ end }}
|
||||||
|
</em></small>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ BlogIndex .Request .V.tag .V.privacy }}
|
{{ BlogIndex .Request .V.tag .V.privacy }}
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
Loading…
Reference in New Issue