2
0
Files
gitcaddy-server/routers/web/explore/blog.go
logikonline c274086c46
All checks were successful
Build and Release / Create Release (push) Successful in 0s
Build and Release / Unit Tests (push) Successful in 3m20s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 5m23s
Build and Release / Lint (push) Successful in 5m40s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 2m59s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 8h4m50s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 7m58s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 8m36s
Build and Release / Build Binary (linux/arm64) (push) Successful in 10m51s
feat(blog): add filtering, sorting, and tags to explore page
Implements search by keyword (title/subtitle), tag filtering, and sort by newest/popular on explore blogs page. Adds GetExploreTopTags to show popular tags with usage counts. Enforces repository access permissions using AccessibleRepositoryCondition. Fixes secret lookup to skip scope conditions when querying by ID. Updates UI with tag cloud, search box, and sort dropdown.
2026-02-01 23:21:05 -05:00

99 lines
2.8 KiB
Go

// Copyright 2026 MarketAlly. All rights reserved.
// SPDX-License-Identifier: MIT
package explore
import (
"net/http"
blog_model "code.gitcaddy.com/server/v3/models/blog"
"code.gitcaddy.com/server/v3/modules/setting"
"code.gitcaddy.com/server/v3/modules/templates"
"code.gitcaddy.com/server/v3/services/context"
)
const tplExploreBlogs templates.TplName = "explore/blogs"
// Blogs renders the explore blogs page with published posts across all repos.
func Blogs(ctx *context.Context) {
if !setting.Config().Theme.EnableBlogs.Value(ctx) {
ctx.Redirect(setting.AppSubURL + "/explore")
return
}
ctx.Data["UsersPageIsDisabled"] = setting.Service.Explore.DisableUsersPage || setting.Config().Theme.HideExploreUsers.Value(ctx)
ctx.Data["OrganizationsPageIsDisabled"] = setting.Service.Explore.DisableOrganizationsPage
ctx.Data["CodePageIsDisabled"] = setting.Service.Explore.DisableCodePage
ctx.Data["PackagesPageIsEnabled"] = setting.Service.Explore.EnablePackagesPage || setting.Config().Theme.EnableExplorePackages.Value(ctx)
ctx.Data["BlogsPageIsEnabled"] = true
ctx.Data["Title"] = ctx.Tr("explore.blogs")
ctx.Data["PageIsExplore"] = true
ctx.Data["PageIsExploreBlogs"] = true
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
page := max(ctx.FormInt("page"), 1)
pageSize := setting.UI.IssuePagingNum
sortType := ctx.FormString("sort")
if sortType != "popular" {
sortType = "newest"
}
ctx.Data["SortType"] = sortType
keyword := ctx.FormTrim("q")
ctx.Data["Keyword"] = keyword
tag := ctx.FormTrim("tag")
ctx.Data["Tag"] = tag
posts, total, err := blog_model.GetExploreBlogPosts(ctx, &blog_model.ExploreBlogPostsOptions{
Actor: ctx.Doer,
Page: page,
PageSize: pageSize,
SortType: sortType,
Keyword: keyword,
Tag: tag,
})
if err != nil {
ctx.ServerError("GetExploreBlogPosts", err)
return
}
// Load authors, repos, and featured images
for _, post := range posts {
_ = post.LoadAuthor(ctx)
_ = post.LoadRepo(ctx)
_ = post.LoadFeaturedImage(ctx)
}
// Only show featured post on page 1 with no search/tag filter
showFeatured := page == 1 && keyword == "" && tag == ""
if showFeatured && len(posts) > 0 {
if counts, err := blog_model.GetBlogReactionCounts(ctx, posts[0].ID); err == nil {
ctx.Data["FeaturedLikes"] = counts.Likes
}
ctx.Data["FeaturedPost"] = posts[0]
if len(posts) > 1 {
ctx.Data["Posts"] = posts[1:]
}
} else {
ctx.Data["Posts"] = posts
}
// Load top tags for sidebar
topTags, err := blog_model.GetExploreTopTags(ctx, ctx.Doer, 10)
if err != nil {
ctx.ServerError("GetExploreTopTags", err)
return
}
ctx.Data["TopTags"] = topTags
ctx.Data["Total"] = total
pager := context.NewPagination(int(total), pageSize, page, 5)
pager.AddParamFromRequest(ctx.Req)
ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, tplExploreBlogs)
}