2021-03-31 03:55:19 +00:00
|
|
|
package website
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"git.handmade.network/hmn/hmn/src/db"
|
|
|
|
"git.handmade.network/hmn/hmn/src/models"
|
|
|
|
"git.handmade.network/hmn/hmn/src/oops"
|
|
|
|
"git.handmade.network/hmn/hmn/src/templates"
|
|
|
|
)
|
|
|
|
|
|
|
|
type LandingTemplateData struct {
|
|
|
|
templates.BaseData
|
|
|
|
|
|
|
|
PostColumns [][]LandingPageProject
|
|
|
|
ShowcaseTimelineJson string
|
|
|
|
}
|
|
|
|
|
|
|
|
type LandingPageProject struct {
|
|
|
|
Project templates.Project
|
2021-04-22 23:02:50 +00:00
|
|
|
FeaturedPost *templates.PostListItem
|
|
|
|
Posts []templates.PostListItem
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|
|
|
|
|
2021-04-06 05:06:19 +00:00
|
|
|
func Index(c *RequestContext) ResponseData {
|
2021-03-31 03:55:19 +00:00
|
|
|
const maxPosts = 5
|
|
|
|
const numProjectsToGet = 7
|
|
|
|
|
2021-04-06 05:06:19 +00:00
|
|
|
iterProjects, err := db.Query(c.Context(), c.Conn, models.Project{},
|
2021-04-11 21:46:06 +00:00
|
|
|
`
|
|
|
|
SELECT $columns
|
|
|
|
FROM handmade_project
|
|
|
|
WHERE
|
|
|
|
flags = 0
|
|
|
|
OR id = $1
|
|
|
|
ORDER BY all_last_updated DESC
|
|
|
|
LIMIT $2
|
|
|
|
`,
|
2021-03-31 03:55:19 +00:00
|
|
|
models.HMNProjectID,
|
2021-04-11 21:46:06 +00:00
|
|
|
numProjectsToGet*2, // hedge your bets against projects that don't have any content
|
2021-03-31 03:55:19 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
2021-04-06 03:30:11 +00:00
|
|
|
return ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to get projects for home page"))
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|
|
|
|
defer iterProjects.Close()
|
|
|
|
|
|
|
|
var pageProjects []LandingPageProject
|
|
|
|
|
2021-04-11 21:46:06 +00:00
|
|
|
allProjects := iterProjects.ToSlice()
|
|
|
|
c.Logger.Info().Interface("allProjects", allProjects).Msg("all the projects")
|
|
|
|
|
2021-04-17 00:01:13 +00:00
|
|
|
var currentUserId *int
|
|
|
|
if c.CurrentUser != nil {
|
|
|
|
currentUserId = &c.CurrentUser.ID
|
|
|
|
}
|
|
|
|
|
2021-04-11 21:46:06 +00:00
|
|
|
for _, projRow := range allProjects {
|
2021-03-31 03:55:19 +00:00
|
|
|
proj := projRow.(*models.Project)
|
|
|
|
|
|
|
|
type ProjectPost struct {
|
2021-04-22 23:02:50 +00:00
|
|
|
Post models.Post `db:"post"`
|
|
|
|
Thread models.Thread `db:"thread"`
|
|
|
|
Cat models.Category `db:"cat"`
|
|
|
|
User models.User `db:"auth_user"`
|
|
|
|
ThreadLastReadTime *time.Time `db:"tlri.lastread"`
|
|
|
|
CatLastReadTime *time.Time `db:"clri.lastread"`
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|
|
|
|
|
2021-04-06 05:06:19 +00:00
|
|
|
projectPostIter, err := db.Query(c.Context(), c.Conn, ProjectPost{},
|
2021-03-31 03:55:19 +00:00
|
|
|
`
|
|
|
|
SELECT $columns
|
|
|
|
FROM
|
|
|
|
handmade_post AS post
|
|
|
|
JOIN handmade_thread AS thread ON thread.id = post.thread_id
|
|
|
|
JOIN handmade_category AS cat ON cat.id = thread.category_id
|
|
|
|
LEFT OUTER JOIN handmade_threadlastreadinfo AS tlri ON (
|
|
|
|
tlri.thread_id = thread.id
|
2021-04-17 00:01:13 +00:00
|
|
|
AND tlri.user_id = $1
|
2021-03-31 03:55:19 +00:00
|
|
|
)
|
|
|
|
LEFT OUTER JOIN handmade_categorylastreadinfo AS clri ON (
|
|
|
|
clri.category_id = cat.id
|
2021-04-17 00:01:13 +00:00
|
|
|
AND clri.user_id = $1
|
2021-03-31 03:55:19 +00:00
|
|
|
)
|
2021-04-22 23:02:50 +00:00
|
|
|
LEFT OUTER JOIN auth_user ON post.author_id = auth_user.id
|
2021-03-31 03:55:19 +00:00
|
|
|
WHERE
|
|
|
|
cat.project_id = $2
|
|
|
|
AND cat.kind IN ($3, $4, $5, $6)
|
|
|
|
AND post.moderated = FALSE
|
|
|
|
AND post.thread_id IS NOT NULL
|
|
|
|
ORDER BY postdate DESC
|
|
|
|
LIMIT $7
|
|
|
|
`,
|
2021-04-17 00:01:13 +00:00
|
|
|
currentUserId,
|
2021-03-31 03:55:19 +00:00
|
|
|
proj.ID,
|
|
|
|
models.CatTypeBlog, models.CatTypeForum, models.CatTypeWiki, models.CatTypeLibraryResource,
|
|
|
|
maxPosts,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
c.Logger.Error().Err(err).Msg("failed to fetch project posts")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
projectPosts := projectPostIter.ToSlice()
|
|
|
|
|
|
|
|
landingPageProject := LandingPageProject{
|
2021-04-11 21:46:06 +00:00
|
|
|
Project: templates.ProjectToTemplate(proj),
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, projectPostRow := range projectPosts {
|
|
|
|
projectPost := projectPostRow.(*ProjectPost)
|
|
|
|
|
|
|
|
hasRead := false
|
|
|
|
if projectPost.ThreadLastReadTime != nil && projectPost.ThreadLastReadTime.After(projectPost.Post.PostDate) {
|
|
|
|
hasRead = true
|
|
|
|
} else if projectPost.CatLastReadTime != nil && projectPost.CatLastReadTime.After(projectPost.Post.PostDate) {
|
|
|
|
hasRead = true
|
|
|
|
}
|
|
|
|
|
2021-04-22 23:02:50 +00:00
|
|
|
c.Logger.Debug().Time("post date", projectPost.Post.PostDate).Msg("")
|
|
|
|
|
|
|
|
landingPageProject.Posts = append(landingPageProject.Posts, templates.PostListItem{
|
|
|
|
Title: projectPost.Thread.Title,
|
|
|
|
Url: templates.PostUrl(projectPost.Post, projectPost.Cat.Kind, proj.Subdomain()), // TODO
|
|
|
|
User: templates.UserToTemplate(&projectPost.User),
|
|
|
|
Date: projectPost.Post.PostDate,
|
|
|
|
Unread: !hasRead,
|
2021-03-31 03:55:19 +00:00
|
|
|
})
|
|
|
|
}
|
2021-04-11 21:46:06 +00:00
|
|
|
|
|
|
|
if len(projectPosts) > 0 {
|
|
|
|
pageProjects = append(pageProjects, landingPageProject)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pageProjects) >= numProjectsToGet {
|
|
|
|
break
|
|
|
|
}
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type newsThreadQuery struct {
|
|
|
|
Thread models.Thread `db:"thread"`
|
|
|
|
}
|
2021-04-06 05:06:19 +00:00
|
|
|
newsThreadRow, err := db.QueryOne(c.Context(), c.Conn, newsThreadQuery{},
|
2021-03-31 03:55:19 +00:00
|
|
|
`
|
|
|
|
SELECT $columns
|
|
|
|
FROM
|
|
|
|
handmade_thread as thread
|
|
|
|
JOIN handmade_category AS cat ON thread.category_id = cat.id
|
|
|
|
WHERE
|
|
|
|
cat.project_id = $1
|
|
|
|
AND cat.kind = $2
|
|
|
|
`,
|
|
|
|
models.HMNProjectID,
|
|
|
|
models.CatTypeBlog,
|
|
|
|
)
|
|
|
|
if err != nil {
|
2021-04-06 03:30:11 +00:00
|
|
|
return ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch latest news post"))
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|
|
|
|
newsThread := newsThreadRow.(*newsThreadQuery)
|
|
|
|
_ = newsThread // TODO: NO
|
|
|
|
|
2021-04-06 05:06:19 +00:00
|
|
|
baseData := getBaseData(c)
|
2021-03-31 03:55:19 +00:00
|
|
|
baseData.BodyClasses = append(baseData.BodyClasses, "hmdev", "landing") // TODO: Is "hmdev" necessary any more?
|
|
|
|
|
2021-04-06 03:30:11 +00:00
|
|
|
var res ResponseData
|
2021-04-11 21:46:06 +00:00
|
|
|
err = res.WriteTemplate("index.html", LandingTemplateData{
|
|
|
|
BaseData: getBaseData(c),
|
|
|
|
PostColumns: [][]LandingPageProject{pageProjects}, // TODO: NO
|
|
|
|
})
|
2021-03-31 03:55:19 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-04-06 03:30:11 +00:00
|
|
|
|
|
|
|
return res
|
2021-03-31 03:55:19 +00:00
|
|
|
}
|