Merge pull request #508 from writefreely/lang-posts-filter
Support filtering blog posts by language Closes T805
This commit is contained in:
commit
334d499fb3
5 changed files with 206 additions and 18 deletions
130
collections.go
130
collections.go
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/writeas/web-core/activitystreams"
|
"github.com/writeas/web-core/activitystreams"
|
||||||
"github.com/writeas/web-core/auth"
|
"github.com/writeas/web-core/auth"
|
||||||
"github.com/writeas/web-core/bots"
|
"github.com/writeas/web-core/bots"
|
||||||
|
"github.com/writeas/web-core/i18n"
|
||||||
"github.com/writeas/web-core/log"
|
"github.com/writeas/web-core/log"
|
||||||
"github.com/writeas/web-core/posts"
|
"github.com/writeas/web-core/posts"
|
||||||
"github.com/writefreely/writefreely/author"
|
"github.com/writefreely/writefreely/author"
|
||||||
|
@ -74,6 +75,7 @@ type (
|
||||||
DisplayCollection struct {
|
DisplayCollection struct {
|
||||||
*CollectionObj
|
*CollectionObj
|
||||||
Prefix string
|
Prefix string
|
||||||
|
NavSuffix string
|
||||||
IsTopLevel bool
|
IsTopLevel bool
|
||||||
CurrentPage int
|
CurrentPage int
|
||||||
TotalPages int
|
TotalPages int
|
||||||
|
@ -261,16 +263,16 @@ func (c *Collection) RedirectingCanonicalURL(isRedir bool) string {
|
||||||
|
|
||||||
// PrevPageURL provides a full URL for the previous page of collection posts,
|
// PrevPageURL provides a full URL for the previous page of collection posts,
|
||||||
// returning a /page/N result for pages >1
|
// returning a /page/N result for pages >1
|
||||||
func (c *Collection) PrevPageURL(prefix string, n int, tl bool) string {
|
func (c *Collection) PrevPageURL(prefix, navSuffix string, n int, tl bool) string {
|
||||||
u := ""
|
u := ""
|
||||||
if n == 2 {
|
if n == 2 {
|
||||||
// Previous page is 1; no need for /page/ prefix
|
// Previous page is 1; no need for /page/ prefix
|
||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
u = "/"
|
u = navSuffix + "/"
|
||||||
}
|
}
|
||||||
// Else leave off trailing slash
|
// Else leave off trailing slash
|
||||||
} else {
|
} else {
|
||||||
u = fmt.Sprintf("/page/%d", n-1)
|
u = fmt.Sprintf("%s/page/%d", navSuffix, n-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tl {
|
if tl {
|
||||||
|
@ -280,11 +282,12 @@ func (c *Collection) PrevPageURL(prefix string, n int, tl bool) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextPageURL provides a full URL for the next page of collection posts
|
// NextPageURL provides a full URL for the next page of collection posts
|
||||||
func (c *Collection) NextPageURL(prefix string, n int, tl bool) string {
|
func (c *Collection) NextPageURL(prefix, navSuffix string, n int, tl bool) string {
|
||||||
|
|
||||||
if tl {
|
if tl {
|
||||||
return fmt.Sprintf("/page/%d", n+1)
|
return fmt.Sprintf("%s/page/%d", navSuffix, n+1)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("/%s%s/page/%d", prefix, c.Alias, n+1)
|
return fmt.Sprintf("/%s%s%s/page/%d", prefix, c.Alias, navSuffix, n+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collection) DisplayTitle() string {
|
func (c *Collection) DisplayTitle() string {
|
||||||
|
@ -389,6 +392,16 @@ func (c CollectionPage) DisplayMonetization() string {
|
||||||
return displayMonetization(c.Monetization, c.Alias)
|
return displayMonetization(c.Monetization, c.Alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *DisplayCollection) Direction() string {
|
||||||
|
if c.Language == "" {
|
||||||
|
return "auto"
|
||||||
|
}
|
||||||
|
if i18n.LangIsRTL(c.Language) {
|
||||||
|
return "rtl"
|
||||||
|
}
|
||||||
|
return "ltr"
|
||||||
|
}
|
||||||
|
|
||||||
func newCollection(app *App, w http.ResponseWriter, r *http.Request) error {
|
func newCollection(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
reqJSON := IsJSON(r)
|
reqJSON := IsJSON(r)
|
||||||
alias := r.FormValue("alias")
|
alias := r.FormValue("alias")
|
||||||
|
@ -1050,6 +1063,111 @@ func handleViewCollectionTag(app *App, w http.ResponseWriter, r *http.Request) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleViewCollectionLang(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
lang := vars["lang"]
|
||||||
|
|
||||||
|
cr := &collectionReq{}
|
||||||
|
err := processCollectionRequest(cr, vars, w, r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := checkUserForCollection(app, cr, r, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
page := getCollectionPage(vars)
|
||||||
|
|
||||||
|
c, err := processCollectionPermissions(app, cr, u, w, r)
|
||||||
|
if c == nil || err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
coll := newDisplayCollection(c, cr, page)
|
||||||
|
coll.Language = lang
|
||||||
|
coll.NavSuffix = fmt.Sprintf("/lang:%s", lang)
|
||||||
|
|
||||||
|
ttlPosts, err := app.db.GetCollLangTotalPosts(coll.ID, lang)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to getCollLangTotalPosts: %s", err)
|
||||||
|
}
|
||||||
|
pagePosts := coll.Format.PostsPerPage()
|
||||||
|
coll.TotalPages = int(math.Ceil(float64(ttlPosts) / float64(pagePosts)))
|
||||||
|
if coll.TotalPages > 0 && page > coll.TotalPages {
|
||||||
|
redirURL := fmt.Sprintf("/lang:%s/page/%d", lang, coll.TotalPages)
|
||||||
|
if !app.cfg.App.SingleUser {
|
||||||
|
redirURL = fmt.Sprintf("/%s%s%s", cr.prefix, coll.Alias, redirURL)
|
||||||
|
}
|
||||||
|
return impart.HTTPError{http.StatusFound, redirURL}
|
||||||
|
}
|
||||||
|
|
||||||
|
coll.Posts, _ = app.db.GetLangPosts(app.cfg, c, lang, page, cr.isCollOwner)
|
||||||
|
if err != nil {
|
||||||
|
return ErrCollectionPageNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serve collection
|
||||||
|
displayPage := struct {
|
||||||
|
CollectionPage
|
||||||
|
Tag string
|
||||||
|
}{
|
||||||
|
CollectionPage: CollectionPage{
|
||||||
|
DisplayCollection: coll,
|
||||||
|
StaticPage: pageForReq(app, r),
|
||||||
|
IsCustomDomain: cr.isCustomDomain,
|
||||||
|
},
|
||||||
|
Tag: lang,
|
||||||
|
}
|
||||||
|
var owner *User
|
||||||
|
if u != nil {
|
||||||
|
displayPage.Username = u.Username
|
||||||
|
displayPage.IsOwner = u.ID == coll.OwnerID
|
||||||
|
if displayPage.IsOwner {
|
||||||
|
// Add in needed information for users viewing their own collection
|
||||||
|
owner = u
|
||||||
|
displayPage.CanPin = true
|
||||||
|
|
||||||
|
pubColls, err := app.db.GetPublishableCollections(owner, app.cfg.App.Host)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("unable to fetch collections: %v", err)
|
||||||
|
}
|
||||||
|
displayPage.Collections = pubColls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isOwner := owner != nil
|
||||||
|
if !isOwner {
|
||||||
|
// Current user doesn't own collection; retrieve owner information
|
||||||
|
owner, err = app.db.GetUserByID(coll.OwnerID)
|
||||||
|
if err != nil {
|
||||||
|
// Log the error and just continue
|
||||||
|
log.Error("Error getting user for collection: %v", err)
|
||||||
|
}
|
||||||
|
if owner.IsSilenced() {
|
||||||
|
return ErrCollectionNotFound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayPage.Silenced = owner != nil && owner.IsSilenced()
|
||||||
|
displayPage.Owner = owner
|
||||||
|
coll.Owner = displayPage.Owner
|
||||||
|
// Add more data
|
||||||
|
// TODO: fix this mess of collections inside collections
|
||||||
|
displayPage.PinnedPosts, _ = app.db.GetPinnedPosts(coll.CollectionObj, isOwner)
|
||||||
|
displayPage.Monetization = app.db.GetCollectionAttribute(coll.ID, "monetization_pointer")
|
||||||
|
|
||||||
|
collTmpl := "collection"
|
||||||
|
if app.cfg.App.Chorus {
|
||||||
|
collTmpl = "chorus-collection"
|
||||||
|
}
|
||||||
|
err = templates[collTmpl].ExecuteTemplate(w, "collection", displayPage)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to render collection lang page: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func handleCollectionPostRedirect(app *App, w http.ResponseWriter, r *http.Request) error {
|
func handleCollectionPostRedirect(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
slug := vars["slug"]
|
slug := vars["slug"]
|
||||||
|
|
68
database.go
68
database.go
|
@ -1346,6 +1346,74 @@ func (db *datastore) GetPostsTagged(cfg *config.Config, c *Collection, tag strin
|
||||||
return &posts, nil
|
return &posts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *datastore) GetCollLangTotalPosts(collID int64, lang string) (uint64, error) {
|
||||||
|
var articles uint64
|
||||||
|
err := db.QueryRow("SELECT COUNT(*) FROM posts WHERE collection_id = ? AND language = ? AND created <= "+db.now(), collID, lang).Scan(&articles)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
log.Error("Couldn't get total lang posts count for collection %d: %v", collID, err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return articles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *datastore) GetLangPosts(cfg *config.Config, c *Collection, lang string, page int, includeFuture bool) (*[]PublicPost, error) {
|
||||||
|
collID := c.ID
|
||||||
|
|
||||||
|
cf := c.NewFormat()
|
||||||
|
order := "DESC"
|
||||||
|
if cf.Ascending() {
|
||||||
|
order = "ASC"
|
||||||
|
}
|
||||||
|
|
||||||
|
pagePosts := cf.PostsPerPage()
|
||||||
|
start := page*pagePosts - pagePosts
|
||||||
|
if page == 0 {
|
||||||
|
start = 0
|
||||||
|
pagePosts = 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
limitStr := ""
|
||||||
|
if page > 0 {
|
||||||
|
limitStr = fmt.Sprintf(" LIMIT %d, %d", start, pagePosts)
|
||||||
|
}
|
||||||
|
timeCondition := ""
|
||||||
|
if !includeFuture {
|
||||||
|
timeCondition = "AND created <= " + db.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := db.Query(`SELECT `+postCols+`
|
||||||
|
FROM posts
|
||||||
|
WHERE collection_id = ? AND language = ? `+timeCondition+`
|
||||||
|
ORDER BY created `+order+limitStr, collID, lang)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed selecting from posts: %v", err)
|
||||||
|
return nil, impart.HTTPError{http.StatusInternalServerError, "Couldn't retrieve collection posts."}
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
// TODO: extract this common row scanning logic for queries using `postCols`
|
||||||
|
posts := []PublicPost{}
|
||||||
|
for rows.Next() {
|
||||||
|
p := &Post{}
|
||||||
|
err = rows.Scan(&p.ID, &p.Slug, &p.Font, &p.Language, &p.RTL, &p.Privacy, &p.OwnerID, &p.CollectionID, &p.PinnedPosition, &p.Created, &p.Updated, &p.ViewCount, &p.Title, &p.Content)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed scanning row: %v", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.extractData()
|
||||||
|
p.augmentContent(c)
|
||||||
|
p.formatContent(cfg, c, includeFuture, false)
|
||||||
|
|
||||||
|
posts = append(posts, p.processPost())
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error after Next() on rows: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &posts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (db *datastore) GetAPFollowers(c *Collection) (*[]RemoteUser, error) {
|
func (db *datastore) GetAPFollowers(c *Collection) (*[]RemoteUser, error) {
|
||||||
rows, err := db.Query("SELECT actor_id, inbox, shared_inbox FROM remotefollows f INNER JOIN remoteusers u ON f.remote_user_id = u.id WHERE collection_id = ?", c.ID)
|
rows, err := db.Query("SELECT actor_id, inbox, shared_inbox FROM remotefollows f INNER JOIN remoteusers u ON f.remote_user_id = u.id WHERE collection_id = ?", c.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -216,6 +216,8 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router {
|
||||||
func RouteCollections(handler *Handler, r *mux.Router) {
|
func RouteCollections(handler *Handler, r *mux.Router) {
|
||||||
r.HandleFunc("/logout", handler.Web(handleLogOutCollection, UserLevelOptional))
|
r.HandleFunc("/logout", handler.Web(handleLogOutCollection, UserLevelOptional))
|
||||||
r.HandleFunc("/page/{page:[0-9]+}", handler.Web(handleViewCollection, UserLevelReader))
|
r.HandleFunc("/page/{page:[0-9]+}", handler.Web(handleViewCollection, UserLevelReader))
|
||||||
|
r.HandleFunc("/lang:{lang:[a-z]{2}}", handler.Web(handleViewCollectionLang, UserLevelOptional))
|
||||||
|
r.HandleFunc("/lang:{lang:[a-z]{2}}/page/{page:[0-9]+}", handler.Web(handleViewCollectionLang, UserLevelOptional))
|
||||||
r.HandleFunc("/tag:{tag}", handler.Web(handleViewCollectionTag, UserLevelReader))
|
r.HandleFunc("/tag:{tag}", handler.Web(handleViewCollectionTag, UserLevelReader))
|
||||||
r.HandleFunc("/tag:{tag}/page/{page:[0-9]+}", handler.Web(handleViewCollectionTag, UserLevelReader))
|
r.HandleFunc("/tag:{tag}/page/{page:[0-9]+}", handler.Web(handleViewCollectionTag, UserLevelReader))
|
||||||
r.HandleFunc("/tag:{tag}/feed/", handler.Web(ViewFeed, UserLevelReader))
|
r.HandleFunc("/tag:{tag}/feed/", handler.Web(ViewFeed, UserLevelReader))
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
{{if .CustomCSS}}<link rel="stylesheet" type="text/css" href="/local/custom.css" />{{end}}
|
{{if .CustomCSS}}<link rel="stylesheet" type="text/css" href="/local/custom.css" />{{end}}
|
||||||
<link rel="shortcut icon" href="/favicon.ico" />
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
<link rel="canonical" href="{{.CanonicalURL}}">
|
<link rel="canonical" href="{{.CanonicalURL}}">
|
||||||
{{if gt .CurrentPage 1}}<link rel="prev" href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">{{end}}
|
{{if gt .CurrentPage 1}}<link rel="prev" href="{{.PrevPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">{{end}}
|
||||||
{{if lt .CurrentPage .TotalPages}}<link rel="next" href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">{{end}}
|
{{if lt .CurrentPage .TotalPages}}<link rel="next" href="{{.NextPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">{{end}}
|
||||||
{{if not .IsPrivate}}<link rel="alternate" type="application/rss+xml" title="{{.DisplayTitle}} » Feed" href="{{.CanonicalURL}}feed/" />{{end}}
|
{{if not .IsPrivate}}<link rel="alternate" type="application/rss+xml" title="{{.DisplayTitle}} » Feed" href="{{.CanonicalURL}}feed/" />{{end}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
|
@ -92,11 +92,11 @@ body#collection header nav.tabs a:first-child {
|
||||||
|
|
||||||
{{if gt .TotalPages 1}}<nav id="paging" class="content-container clearfix">
|
{{if gt .TotalPages 1}}<nav id="paging" class="content-container clearfix">
|
||||||
{{if or (and .Format.Ascending (le .CurrentPage .TotalPages)) (isRTL .Direction)}}
|
{{if or (and .Format.Ascending (le .CurrentPage .TotalPages)) (isRTL .Direction)}}
|
||||||
{{if gt .CurrentPage 1}}<a href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">⇠ {{if and .Format.Ascending (le .CurrentPage .TotalPages)}}Previous{{else}}Newer{{end}}</a>{{end}}
|
{{if gt .CurrentPage 1}}<a href="{{.PrevPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">⇠ {{if and .Format.Ascending (le .CurrentPage .TotalPages)}}Previous{{else}}Newer{{end}}</a>{{end}}
|
||||||
{{if lt .CurrentPage .TotalPages}}<a style="float:right;" href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">{{if and .Format.Ascending (lt .CurrentPage .TotalPages)}}Next{{else}}Older{{end}} ⇢</a>{{end}}
|
{{if lt .CurrentPage .TotalPages}}<a style="float:right;" href="{{.NextPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">{{if and .Format.Ascending (lt .CurrentPage .TotalPages)}}Next{{else}}Older{{end}} ⇢</a>{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if lt .CurrentPage .TotalPages}}<a href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">⇠ Older</a>{{end}}
|
{{if lt .CurrentPage .TotalPages}}<a href="{{.NextPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">⇠ Older</a>{{end}}
|
||||||
{{if gt .CurrentPage 1}}<a style="float:right;" href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">Newer ⇢</a>{{end}}
|
{{if gt .CurrentPage 1}}<a style="float:right;" href="{{.PrevPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">Newer ⇢</a>{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</nav>{{end}}
|
</nav>{{end}}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
{{if .CustomCSS}}<link rel="stylesheet" type="text/css" href="/local/custom.css" />{{end}}
|
{{if .CustomCSS}}<link rel="stylesheet" type="text/css" href="/local/custom.css" />{{end}}
|
||||||
<link rel="shortcut icon" href="/favicon.ico" />
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
<link rel="canonical" href="{{.CanonicalURL}}">
|
<link rel="canonical" href="{{.CanonicalURL}}">
|
||||||
{{if gt .CurrentPage 1}}<link rel="prev" href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">{{end}}
|
{{if gt .CurrentPage 1}}<link rel="prev" href="{{.PrevPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">{{end}}
|
||||||
{{if lt .CurrentPage .TotalPages}}<link rel="next" href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">{{end}}
|
{{if lt .CurrentPage .TotalPages}}<link rel="next" href="{{.NextPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">{{end}}
|
||||||
{{if not .IsPrivate}}<link rel="alternate" type="application/rss+xml" title="{{.DisplayTitle}} » Feed" href="{{.CanonicalURL}}feed/" />{{end}}
|
{{if not .IsPrivate}}<link rel="alternate" type="application/rss+xml" title="{{.DisplayTitle}} » Feed" href="{{.CanonicalURL}}feed/" />{{end}}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
|
@ -107,11 +107,11 @@
|
||||||
|
|
||||||
{{if gt .TotalPages 1}}<nav id="paging" class="content-container clearfix">
|
{{if gt .TotalPages 1}}<nav id="paging" class="content-container clearfix">
|
||||||
{{if or (and .Format.Ascending (le .CurrentPage .TotalPages)) (isRTL .Direction)}}
|
{{if or (and .Format.Ascending (le .CurrentPage .TotalPages)) (isRTL .Direction)}}
|
||||||
{{if gt .CurrentPage 1}}<a href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">⇠ {{if and .Format.Ascending (le .CurrentPage .TotalPages)}}Previous{{else}}Newer{{end}}</a>{{end}}
|
{{if gt .CurrentPage 1}}<a href="{{.PrevPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">⇠ {{if and .Format.Ascending (le .CurrentPage .TotalPages)}}Previous{{else}}Newer{{end}}</a>{{end}}
|
||||||
{{if lt .CurrentPage .TotalPages}}<a style="float:right;" href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">{{if and .Format.Ascending (lt .CurrentPage .TotalPages)}}Next{{else}}Older{{end}} ⇢</a>{{end}}
|
{{if lt .CurrentPage .TotalPages}}<a style="float:right;" href="{{.NextPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">{{if and .Format.Ascending (lt .CurrentPage .TotalPages)}}Next{{else}}Older{{end}} ⇢</a>{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if lt .CurrentPage .TotalPages}}<a href="{{.NextPageURL .Prefix .CurrentPage .IsTopLevel}}">⇠ Older</a>{{end}}
|
{{if lt .CurrentPage .TotalPages}}<a href="{{.NextPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">⇠ Older</a>{{end}}
|
||||||
{{if gt .CurrentPage 1}}<a style="float:right;" href="{{.PrevPageURL .Prefix .CurrentPage .IsTopLevel}}">Newer ⇢</a>{{end}}
|
{{if gt .CurrentPage 1}}<a style="float:right;" href="{{.PrevPageURL .Prefix .NavSuffix .CurrentPage .IsTopLevel}}">Newer ⇢</a>{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</nav>{{end}}
|
</nav>{{end}}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue