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
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.
99 lines
2.8 KiB
Go
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)
|
|
}
|