hmn/src/website/landing.go

160 lines
5.1 KiB
Go
Raw Normal View History

package website
import (
2021-04-24 04:27:45 +00:00
"html/template"
2021-10-24 20:48:28 +00:00
"math"
"net/http"
"git.handmade.network/hmn/hmn/src/hmndata"
2021-05-11 22:53:23 +00:00
"git.handmade.network/hmn/hmn/src/hmnurl"
"git.handmade.network/hmn/hmn/src/models"
"git.handmade.network/hmn/hmn/src/oops"
"git.handmade.network/hmn/hmn/src/templates"
2021-10-24 20:48:28 +00:00
"git.handmade.network/hmn/hmn/src/utils"
)
type LandingTemplateData struct {
templates.BaseData
2021-10-24 20:48:28 +00:00
NewsPost *templates.TimelineItem
TimelineItems []templates.TimelineItem
Pagination templates.Pagination
ShowcaseTimelineJson string
2021-05-11 22:53:23 +00:00
2021-10-26 04:42:55 +00:00
ManifestoUrl string
2021-10-24 20:48:28 +00:00
FeedUrl string
PodcastUrl string
StreamsUrl string
ShowcaseUrl string
AtomFeedUrl string
MarkAllReadUrl string
2021-08-28 11:26:17 +00:00
2022-06-18 15:30:30 +00:00
JamUrl string
}
func Index(c *RequestContext) ResponseData {
c.Perf.StartBlock("SQL", "Fetch subforum tree")
subforumTree := models.GetFullSubforumTree(c, c.Conn)
lineageBuilder := models.MakeSubforumLineageBuilder(subforumTree)
2021-05-11 22:53:23 +00:00
c.Perf.EndBlock()
2021-10-24 20:48:28 +00:00
var timelineItems []templates.TimelineItem
2021-04-22 23:02:50 +00:00
numPosts, err := hmndata.CountPosts(c, c.Conn, c.CurrentUser, hmndata.PostsQuery{
2021-10-24 20:48:28 +00:00
ThreadTypes: feedThreadTypes,
})
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, err)
}
2021-10-24 20:48:28 +00:00
numPages := int(math.Ceil(float64(numPosts) / feedPostsPerPage))
2021-04-23 04:07:44 +00:00
2021-10-24 20:48:28 +00:00
page, numPages, ok := getPageInfo("1", numPosts, feedPostsPerPage)
if !ok {
return c.Redirect(hmnurl.BuildFeed(), http.StatusSeeOther)
}
2021-04-23 04:07:44 +00:00
2021-10-24 20:48:28 +00:00
pagination := templates.Pagination{
Current: page,
Total: numPages,
2021-04-23 04:07:44 +00:00
2021-10-24 20:48:28 +00:00
FirstUrl: hmnurl.BuildFeed(),
LastUrl: hmnurl.BuildFeedWithPage(numPages),
NextUrl: hmnurl.BuildFeedWithPage(utils.IntClamp(1, page+1, numPages)),
PreviousUrl: hmnurl.BuildFeedWithPage(utils.IntClamp(1, page-1, numPages)),
}
2021-04-23 04:07:44 +00:00
2021-10-24 20:48:28 +00:00
// This is essentially an alternate for feed page 1.
posts, err := hmndata.FetchPosts(c, c.Conn, c.CurrentUser, hmndata.PostsQuery{
2021-10-24 20:48:28 +00:00
ThreadTypes: feedThreadTypes,
Limit: feedPostsPerPage,
SortDescending: true,
})
if err != nil {
c.Logger.Warn().Err(err).Msg("failed to fetch latest posts")
}
for _, p := range posts {
item := PostToTimelineItem(hmndata.UrlContextForProject(&p.Project), lineageBuilder, &p.Post, &p.Thread, p.Author, c.Theme)
2021-10-24 20:48:28 +00:00
if p.Thread.Type == models.ThreadTypeProjectBlogPost && p.Post.ID == p.Thread.FirstID {
// blog post
item.Description = template.HTML(p.CurrentVersion.TextParsed)
item.TruncateDescription = true
2021-04-23 04:07:44 +00:00
}
2021-10-24 20:48:28 +00:00
timelineItems = append(timelineItems, item)
2021-04-23 04:07:44 +00:00
}
2021-05-11 22:53:23 +00:00
c.Perf.StartBlock("SQL", "Get news")
newsThreads, err := hmndata.FetchThreads(c, c.Conn, c.CurrentUser, hmndata.ThreadsQuery{
ProjectIDs: []int{models.HMNProjectID},
ThreadTypes: []models.ThreadType{models.ThreadTypeProjectBlogPost},
Limit: 1,
})
2021-04-24 04:27:45 +00:00
if err != nil {
2021-08-28 12:21:03 +00:00
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch news post"))
2021-04-24 04:27:45 +00:00
}
2021-10-24 20:48:28 +00:00
var newsPostItem *templates.TimelineItem
if len(newsThreads) > 0 {
2021-10-24 20:48:28 +00:00
t := newsThreads[0]
item := PostToTimelineItem(hmndata.UrlContextForProject(&t.Project), lineageBuilder, &t.FirstPost, &t.Thread, t.FirstPostAuthor, c.Theme)
2021-10-25 14:07:14 +00:00
item.OwnerAvatarUrl = ""
item.Breadcrumbs = nil
2021-10-24 20:48:28 +00:00
item.TypeTitle = ""
2021-10-25 14:07:14 +00:00
item.AllowTitleWrap = true
2021-10-24 20:48:28 +00:00
item.Description = template.HTML(t.FirstPostCurrentVersion.TextParsed)
item.TruncateDescription = true
newsPostItem = &item
}
2021-05-11 22:53:23 +00:00
c.Perf.EndBlock()
2021-04-24 04:27:45 +00:00
snippets, err := hmndata.FetchSnippets(c, c.Conn, c.CurrentUser, hmndata.SnippetQuery{
2021-11-11 19:00:46 +00:00
Limit: 40,
})
2021-06-23 19:31:59 +00:00
if err != nil {
2021-08-28 12:21:03 +00:00
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch snippets"))
2021-06-23 19:31:59 +00:00
}
2021-11-11 19:00:46 +00:00
showcaseItems := make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets {
2022-08-05 04:03:45 +00:00
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false)
if timelineItem.CanShowcase {
2021-06-23 19:31:59 +00:00
showcaseItems = append(showcaseItems, timelineItem)
}
}
c.Perf.EndBlock()
c.Perf.StartBlock("SHOWCASE", "Convert to json")
showcaseJson := templates.TimelineItemsToJSON(showcaseItems)
c.Perf.EndBlock()
2021-09-01 18:25:09 +00:00
baseData := getBaseData(c, "", nil)
baseData.BodyClasses = append(baseData.BodyClasses, "hmdev", "landing") // TODO: Is "hmdev" necessary any more?
2021-09-09 02:51:43 +00:00
baseData.OpenGraphItems = append(baseData.OpenGraphItems, templates.OpenGraphItem{
Property: "og:description",
2021-09-09 03:00:28 +00:00
Value: "A community of programmers committed to producing quality software through deeper understanding.",
2021-09-09 02:51:43 +00:00
})
var res ResponseData
err = res.WriteTemplate("landing.html", LandingTemplateData{
2021-10-24 20:48:28 +00:00
BaseData: baseData,
NewsPost: newsPostItem,
TimelineItems: timelineItems,
Pagination: pagination,
2021-06-23 19:31:59 +00:00
ShowcaseTimelineJson: showcaseJson,
2021-08-28 11:26:17 +00:00
2021-10-26 04:42:55 +00:00
ManifestoUrl: hmnurl.BuildManifesto(),
2021-10-24 20:48:28 +00:00
FeedUrl: hmnurl.BuildFeed(),
PodcastUrl: hmnurl.BuildPodcast(),
2021-10-24 20:48:28 +00:00
StreamsUrl: hmnurl.BuildStreams(),
ShowcaseUrl: hmnurl.BuildShowcase(),
AtomFeedUrl: hmnurl.BuildAtomFeed(),
MarkAllReadUrl: hmnurl.HMNProjectContext.BuildForumMarkRead(0),
2021-10-24 20:48:28 +00:00
2022-06-18 15:30:30 +00:00
JamUrl: hmnurl.BuildJamIndex(),
2021-04-26 06:56:49 +00:00
}, c.Perf)
if err != nil {
2021-08-28 12:21:03 +00:00
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render landing page template"))
}
return res
}