Per-topic views are now visible in the topic pages for the Nox Theme.
The parent forum of a topic is now visible on the topic pages for the Cosora and Nox Themes. Added basic styling for polls to the Nox Theme. Improved the styling for topic title editing in the Nox Theme.
This commit is contained in:
parent
41c3a5bb4a
commit
39adc2e606
|
@ -94,6 +94,7 @@ type TopicPage struct {
|
||||||
*Header
|
*Header
|
||||||
ItemList []ReplyUser
|
ItemList []ReplyUser
|
||||||
Topic TopicUser
|
Topic TopicUser
|
||||||
|
Forum *Forum
|
||||||
Poll Poll
|
Poll Poll
|
||||||
Page int
|
Page int
|
||||||
LastPage int
|
LastPage int
|
||||||
|
|
|
@ -189,7 +189,7 @@ func CompileTemplates() error {
|
||||||
PollOption{1, "Something"},
|
PollOption{1, "Something"},
|
||||||
}, VoteCount: 7}
|
}, VoteCount: 7}
|
||||||
avatar, microAvatar := BuildAvatar(62, "")
|
avatar, microAvatar := BuildAvatar(62, "")
|
||||||
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, RelativeTime(now), now, RelativeTime(now), 0, "", "127.0.0.1", 0, 1, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false}
|
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, RelativeTime(now), now, RelativeTime(now), 0, "", "127.0.0.1", 1, 0, 1, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false}
|
||||||
var replyList []ReplyUser
|
var replyList []ReplyUser
|
||||||
// TODO: Do we want the UID on this to be 0?
|
// TODO: Do we want the UID on this to be 0?
|
||||||
avatar, microAvatar = BuildAvatar(0, "")
|
avatar, microAvatar = BuildAvatar(0, "")
|
||||||
|
@ -197,7 +197,8 @@ func CompileTemplates() error {
|
||||||
|
|
||||||
var varList = make(map[string]tmpl.VarItem)
|
var varList = make(map[string]tmpl.VarItem)
|
||||||
header.Title = "Topic Name"
|
header.Title = "Topic Name"
|
||||||
tpage := TopicPage{header, replyList, topic, poll, 1, 1}
|
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
||||||
|
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
||||||
topicIDTmpl, err := c.Compile("topic.html", "templates/", "common.TopicPage", tpage, varList)
|
topicIDTmpl, err := c.Compile("topic.html", "templates/", "common.TopicPage", tpage, varList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -234,7 +235,7 @@ func CompileTemplates() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var topicsList []*TopicsRow
|
var topicsList []*TopicsRow
|
||||||
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, "Date", user3.ID, 1, "", "127.0.0.1", 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"})
|
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, "Date", user3.ID, 1, "", "127.0.0.1", 1, 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"})
|
||||||
header2.Title = "Topic List"
|
header2.Title = "Topic List"
|
||||||
topicListPage := TopicListPage{header, topicsList, forumList, Config.DefaultForum, Paginator{[]int{1}, 1, 1}}
|
topicListPage := TopicListPage{header, topicsList, forumList, Config.DefaultForum, Paginator{[]int{1}, 1, 1}}
|
||||||
topicListTmpl, err := c.Compile("topics.html", "templates/", "common.TopicListPage", topicListPage, varList)
|
topicListTmpl, err := c.Compile("topics.html", "templates/", "common.TopicListPage", topicListPage, varList)
|
||||||
|
@ -365,7 +366,7 @@ func CompileJSTemplates() error {
|
||||||
// TODO: Fix the import loop so we don't have to use this hack anymore
|
// TODO: Fix the import loop so we don't have to use this hack anymore
|
||||||
c.SetBuildTags("!no_templategen,tmplgentopic")
|
c.SetBuildTags("!no_templategen,tmplgentopic")
|
||||||
|
|
||||||
var topicsRow = &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, "Date", user3.ID, 1, "", "127.0.0.1", 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"}
|
var topicsRow = &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, "Date", user3.ID, 1, "", "127.0.0.1", 1, 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"}
|
||||||
topicListItemTmpl, err := c.Compile("topics_topic.html", "templates/", "*common.TopicsRow", topicsRow, varList)
|
topicListItemTmpl, err := c.Compile("topics_topic.html", "templates/", "*common.TopicsRow", topicsRow, varList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -376,7 +377,7 @@ func CompileJSTemplates() error {
|
||||||
PollOption{1, "Something"},
|
PollOption{1, "Something"},
|
||||||
}, VoteCount: 7}
|
}, VoteCount: 7}
|
||||||
avatar, microAvatar := BuildAvatar(62, "")
|
avatar, microAvatar := BuildAvatar(62, "")
|
||||||
topic := TopicUser{1, "blah", "Blah", "Hey there!", 62, false, false, now, RelativeTime(now), now, RelativeTime(now), 0, "", "127.0.0.1", 0, 1, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false}
|
topic := TopicUser{1, "blah", "Blah", "Hey there!", 62, false, false, now, RelativeTime(now), now, RelativeTime(now), 0, "", "127.0.0.1", 1, 0, 1, "classname", poll.ID, "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, avatar, microAvatar, 0, "", "", "", "", "", 58, false}
|
||||||
var replyList []ReplyUser
|
var replyList []ReplyUser
|
||||||
// TODO: Do we really want the UID here to be zero?
|
// TODO: Do we really want the UID here to be zero?
|
||||||
avatar, microAvatar = BuildAvatar(0, "")
|
avatar, microAvatar = BuildAvatar(0, "")
|
||||||
|
@ -384,7 +385,8 @@ func CompileJSTemplates() error {
|
||||||
|
|
||||||
varList = make(map[string]tmpl.VarItem)
|
varList = make(map[string]tmpl.VarItem)
|
||||||
header.Title = "Topic Name"
|
header.Title = "Topic Name"
|
||||||
tpage := TopicPage{header, replyList, topic, poll, 1, 1}
|
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, 1, 1}
|
||||||
|
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
|
||||||
topicIDTmpl, err := c.Compile("topic_posts.html", "templates/", "common.TopicPage", tpage, varList)
|
topicIDTmpl, err := c.Compile("topic_posts.html", "templates/", "common.TopicPage", tpage, varList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -37,6 +37,7 @@ type Topic struct {
|
||||||
ParentID int
|
ParentID int
|
||||||
Status string // Deprecated. Marked for removal.
|
Status string // Deprecated. Marked for removal.
|
||||||
IPAddress string
|
IPAddress string
|
||||||
|
ViewCount int
|
||||||
PostCount int
|
PostCount int
|
||||||
LikeCount int
|
LikeCount int
|
||||||
ClassName string // CSS Class Name
|
ClassName string // CSS Class Name
|
||||||
|
@ -60,6 +61,7 @@ type TopicUser struct {
|
||||||
ParentID int
|
ParentID int
|
||||||
Status string // Deprecated. Marked for removal.
|
Status string // Deprecated. Marked for removal.
|
||||||
IPAddress string
|
IPAddress string
|
||||||
|
ViewCount int
|
||||||
PostCount int
|
PostCount int
|
||||||
LikeCount int
|
LikeCount int
|
||||||
ClassName string
|
ClassName string
|
||||||
|
@ -97,6 +99,7 @@ type TopicsRow struct {
|
||||||
ParentID int
|
ParentID int
|
||||||
Status string // Deprecated. Marked for removal. -Is there anything we could use it for?
|
Status string // Deprecated. Marked for removal. -Is there anything we could use it for?
|
||||||
IPAddress string
|
IPAddress string
|
||||||
|
ViewCount int
|
||||||
PostCount int
|
PostCount int
|
||||||
LikeCount int
|
LikeCount int
|
||||||
ClassName string
|
ClassName string
|
||||||
|
@ -123,6 +126,7 @@ type WsTopicsRow struct {
|
||||||
RelativeLastReplyAt string
|
RelativeLastReplyAt string
|
||||||
LastReplyBy int
|
LastReplyBy int
|
||||||
ParentID int
|
ParentID int
|
||||||
|
ViewCount int
|
||||||
PostCount int
|
PostCount int
|
||||||
LikeCount int
|
LikeCount int
|
||||||
ClassName string
|
ClassName string
|
||||||
|
@ -133,7 +137,7 @@ type WsTopicsRow struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (row *TopicsRow) WebSockets() *WsTopicsRow {
|
func (row *TopicsRow) WebSockets() *WsTopicsRow {
|
||||||
return &WsTopicsRow{row.ID, row.Link, row.Title, row.CreatedBy, row.IsClosed, row.Sticky, row.CreatedAt, row.LastReplyAt, row.RelativeLastReplyAt, row.LastReplyBy, row.ParentID, row.PostCount, row.LikeCount, row.ClassName, row.Creator.WebSockets(), row.LastUser.WebSockets(), row.ForumName, row.ForumLink}
|
return &WsTopicsRow{row.ID, row.Link, row.Title, row.CreatedBy, row.IsClosed, row.Sticky, row.CreatedAt, row.LastReplyAt, row.RelativeLastReplyAt, row.LastReplyBy, row.ParentID, row.ViewCount, row.PostCount, row.LikeCount, row.ClassName, row.Creator.WebSockets(), row.LastUser.WebSockets(), row.ForumName, row.ForumLink}
|
||||||
}
|
}
|
||||||
|
|
||||||
type TopicStmts struct {
|
type TopicStmts struct {
|
||||||
|
@ -174,8 +178,8 @@ func init() {
|
||||||
setPoll: acc.Update("topics").Set("content = '', parsed_content = '', poll = ?").Where("tid = ? AND poll = 0").Prepare(),
|
setPoll: acc.Update("topics").Set("content = '', parsed_content = '', poll = ?").Where("tid = ? AND poll = 0").Prepare(),
|
||||||
createActionReply: acc.Insert("replies").Columns("tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''").Prepare(),
|
createActionReply: acc.Insert("replies").Columns("tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''").Prepare(),
|
||||||
|
|
||||||
getTopicUser: acc.SimpleLeftJoin("topics", "users", "topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, topics.poll, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level", "topics.createdBy = users.uid", "tid = ?", "", ""),
|
getTopicUser: acc.SimpleLeftJoin("topics", "users", "topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.views, topics.postCount, topics.likeCount, topics.poll, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level", "topics.createdBy = users.uid", "tid = ?", "", ""),
|
||||||
getByReplyID: acc.SimpleLeftJoin("replies", "topics", "topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, topics.poll, topics.data", "replies.tid = topics.tid", "rid = ?", "", ""),
|
getByReplyID: acc.SimpleLeftJoin("replies", "topics", "topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.views, topics.postCount, topics.likeCount, topics.poll, topics.data", "replies.tid = topics.tid", "rid = ?", "", ""),
|
||||||
}
|
}
|
||||||
return acc.FirstError()
|
return acc.FirstError()
|
||||||
})
|
})
|
||||||
|
@ -332,7 +336,7 @@ func (topic *Topic) Copy() Topic {
|
||||||
// TODO: Load LastReplyAt?
|
// TODO: Load LastReplyAt?
|
||||||
func TopicByReplyID(rid int) (*Topic, error) {
|
func TopicByReplyID(rid int) (*Topic, error) {
|
||||||
topic := Topic{ID: 0}
|
topic := Topic{ID: 0}
|
||||||
err := topicStmts.getByReplyID.QueryRow(rid).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
err := topicStmts.getByReplyID.QueryRow(rid).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.ViewCount, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
||||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), topic.ID)
|
topic.Link = BuildTopicURL(NameToSlug(topic.Title), topic.ID)
|
||||||
return &topic, err
|
return &topic, err
|
||||||
}
|
}
|
||||||
|
@ -366,14 +370,14 @@ func GetTopicUser(tid int) (TopicUser, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tu := TopicUser{ID: tid}
|
tu := TopicUser{ID: tid}
|
||||||
err := topicStmts.getTopicUser.QueryRow(tid).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.Poll, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
|
err := topicStmts.getTopicUser.QueryRow(tid).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.ViewCount, &tu.PostCount, &tu.LikeCount, &tu.Poll, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
|
||||||
tu.Avatar, tu.MicroAvatar = BuildAvatar(tu.CreatedBy, tu.Avatar)
|
tu.Avatar, tu.MicroAvatar = BuildAvatar(tu.CreatedBy, tu.Avatar)
|
||||||
tu.Link = BuildTopicURL(NameToSlug(tu.Title), tu.ID)
|
tu.Link = BuildTopicURL(NameToSlug(tu.Title), tu.ID)
|
||||||
tu.UserLink = BuildProfileURL(NameToSlug(tu.CreatedByName), tu.CreatedBy)
|
tu.UserLink = BuildProfileURL(NameToSlug(tu.CreatedByName), tu.CreatedBy)
|
||||||
tu.Tag = Groups.DirtyGet(tu.Group).Tag
|
tu.Tag = Groups.DirtyGet(tu.Group).Tag
|
||||||
|
|
||||||
if tcache != nil {
|
if tcache != nil {
|
||||||
theTopic := Topic{ID: tu.ID, Link: tu.Link, Title: tu.Title, Content: tu.Content, CreatedBy: tu.CreatedBy, IsClosed: tu.IsClosed, Sticky: tu.Sticky, CreatedAt: tu.CreatedAt, LastReplyAt: tu.LastReplyAt, ParentID: tu.ParentID, IPAddress: tu.IPAddress, PostCount: tu.PostCount, LikeCount: tu.LikeCount, Poll: tu.Poll}
|
theTopic := Topic{ID: tu.ID, Link: tu.Link, Title: tu.Title, Content: tu.Content, CreatedBy: tu.CreatedBy, IsClosed: tu.IsClosed, Sticky: tu.Sticky, CreatedAt: tu.CreatedAt, LastReplyAt: tu.LastReplyAt, ParentID: tu.ParentID, IPAddress: tu.IPAddress, ViewCount: tu.ViewCount, PostCount: tu.PostCount, LikeCount: tu.LikeCount, Poll: tu.Poll}
|
||||||
//log.Printf("theTopic: %+v\n", theTopic)
|
//log.Printf("theTopic: %+v\n", theTopic)
|
||||||
_ = tcache.Add(&theTopic)
|
_ = tcache.Add(&theTopic)
|
||||||
}
|
}
|
||||||
|
@ -401,6 +405,7 @@ func copyTopicToTopicUser(topic *Topic, user *User) (tu TopicUser) {
|
||||||
tu.LastReplyAt = topic.LastReplyAt
|
tu.LastReplyAt = topic.LastReplyAt
|
||||||
tu.ParentID = topic.ParentID
|
tu.ParentID = topic.ParentID
|
||||||
tu.IPAddress = topic.IPAddress
|
tu.IPAddress = topic.IPAddress
|
||||||
|
tu.ViewCount = topic.ViewCount
|
||||||
tu.PostCount = topic.PostCount
|
tu.PostCount = topic.PostCount
|
||||||
tu.LikeCount = topic.LikeCount
|
tu.LikeCount = topic.LikeCount
|
||||||
tu.Poll = topic.Poll
|
tu.Poll = topic.Poll
|
||||||
|
|
|
@ -216,7 +216,7 @@ func (tList *DefaultTopicList) getList(page int, argList []interface{}, qlist st
|
||||||
}
|
}
|
||||||
offset, page, lastPage := PageOffset(topicCount, page, Config.ItemsPerPage)
|
offset, page, lastPage := PageOffset(topicCount, page, Config.ItemsPerPage)
|
||||||
|
|
||||||
stmt, err := qgen.Builder.SimpleSelect("topics", "tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount", "parentID IN("+qlist+")", "sticky DESC, lastReplyAt DESC, createdBy DESC", "?,?")
|
stmt, err := qgen.Builder.SimpleSelect("topics", "tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, views, postCount, likeCount", "parentID IN("+qlist+")", "sticky DESC, lastReplyAt DESC, createdBy DESC", "?,?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Paginator{nil, 1, 1}, err
|
return nil, Paginator{nil, 1, 1}, err
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ func (tList *DefaultTopicList) getList(page int, argList []interface{}, qlist st
|
||||||
var reqUserList = make(map[int]bool)
|
var reqUserList = make(map[int]bool)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
topicItem := TopicsRow{ID: 0}
|
topicItem := TopicsRow{ID: 0}
|
||||||
err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.IsClosed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.PostCount, &topicItem.LikeCount)
|
err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.IsClosed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.ViewCount, &topicItem.PostCount, &topicItem.LikeCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Paginator{nil, 1, 1}, err
|
return nil, Paginator{nil, 1, 1}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ func NewDefaultTopicStore(cache TopicCache) (*DefaultTopicStore, error) {
|
||||||
}
|
}
|
||||||
return &DefaultTopicStore{
|
return &DefaultTopicStore{
|
||||||
cache: cache,
|
cache: cache,
|
||||||
get: acc.Select("topics").Columns("title, content, createdBy, createdAt, lastReplyAt, is_closed, sticky, parentID, ipaddress, postCount, likeCount, poll, data").Where("tid = ?").Prepare(),
|
get: acc.Select("topics").Columns("title, content, createdBy, createdAt, lastReplyAt, is_closed, sticky, parentID, ipaddress, views, postCount, likeCount, poll, data").Where("tid = ?").Prepare(),
|
||||||
exists: acc.Select("topics").Columns("tid").Where("tid = ?").Prepare(),
|
exists: acc.Select("topics").Columns("tid").Where("tid = ?").Prepare(),
|
||||||
topicCount: acc.Count("topics").Prepare(),
|
topicCount: acc.Count("topics").Prepare(),
|
||||||
create: acc.Insert("topics").Columns("parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?").Prepare(),
|
create: acc.Insert("topics").Columns("parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?").Prepare(),
|
||||||
|
@ -71,7 +71,7 @@ func (mts *DefaultTopicStore) DirtyGet(id int) *Topic {
|
||||||
}
|
}
|
||||||
|
|
||||||
topic = &Topic{ID: id}
|
topic = &Topic{ID: id}
|
||||||
err = mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
err = mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.ViewCount, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||||
_ = mts.cache.Add(topic)
|
_ = mts.cache.Add(topic)
|
||||||
|
@ -88,7 +88,7 @@ func (mts *DefaultTopicStore) Get(id int) (topic *Topic, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
topic = &Topic{ID: id}
|
topic = &Topic{ID: id}
|
||||||
err = mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
err = mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.ViewCount, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||||
_ = mts.cache.Add(topic)
|
_ = mts.cache.Add(topic)
|
||||||
|
@ -99,14 +99,14 @@ func (mts *DefaultTopicStore) Get(id int) (topic *Topic, err error) {
|
||||||
// BypassGet will always bypass the cache and pull the topic directly from the database
|
// BypassGet will always bypass the cache and pull the topic directly from the database
|
||||||
func (mts *DefaultTopicStore) BypassGet(id int) (*Topic, error) {
|
func (mts *DefaultTopicStore) BypassGet(id int) (*Topic, error) {
|
||||||
topic := &Topic{ID: id}
|
topic := &Topic{ID: id}
|
||||||
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.ViewCount, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
||||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||||
return topic, err
|
return topic, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mts *DefaultTopicStore) Reload(id int) error {
|
func (mts *DefaultTopicStore) Reload(id int) error {
|
||||||
topic := &Topic{ID: id}
|
topic := &Topic{ID: id}
|
||||||
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.ViewCount, &topic.PostCount, &topic.LikeCount, &topic.Poll, &topic.Data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||||
_ = mts.cache.Set(topic)
|
_ = mts.cache.Set(topic)
|
||||||
|
|
|
@ -762,7 +762,7 @@ func BenchmarkQueryTopicParallel(b *testing.B) {
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
var tu common.TopicUser
|
var tu common.TopicUser
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
|
err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.views, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.ViewCount, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
log.Fatal("No rows found!")
|
log.Fatal("No rows found!")
|
||||||
return
|
return
|
||||||
|
|
|
@ -21,7 +21,7 @@ var forumStmts ForumStmts
|
||||||
func init() {
|
func init() {
|
||||||
common.DbInits.Add(func(acc *qgen.Accumulator) error {
|
common.DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||||
forumStmts = ForumStmts{
|
forumStmts = ForumStmts{
|
||||||
getTopics: acc.Select("topics").Columns("tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount").Where("parentID = ?").Orderby("sticky DESC, lastReplyAt DESC, createdBy DESC").Limit("?,?").Prepare(),
|
getTopics: acc.Select("topics").Columns("tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, views, postCount, likeCount").Where("parentID = ?").Orderby("sticky DESC, lastReplyAt DESC, createdBy DESC").Limit("?,?").Prepare(),
|
||||||
}
|
}
|
||||||
return acc.FirstError()
|
return acc.FirstError()
|
||||||
})
|
})
|
||||||
|
@ -73,7 +73,7 @@ func ViewForum(w http.ResponseWriter, r *http.Request, user common.User, sfid st
|
||||||
var reqUserList = make(map[int]bool)
|
var reqUserList = make(map[int]bool)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var topicItem = common.TopicsRow{ID: 0}
|
var topicItem = common.TopicsRow{ID: 0}
|
||||||
err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.IsClosed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.PostCount, &topicItem.LikeCount)
|
err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.IsClosed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.ViewCount, &topicItem.PostCount, &topicItem.LikeCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,11 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
|
||||||
}
|
}
|
||||||
topic.RelativeCreatedAt = common.RelativeTime(topic.CreatedAt)
|
topic.RelativeCreatedAt = common.RelativeTime(topic.CreatedAt)
|
||||||
|
|
||||||
|
forum, err := common.Forums.Get(topic.ParentID)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
var poll common.Poll
|
var poll common.Poll
|
||||||
if topic.Poll != 0 {
|
if topic.Poll != 0 {
|
||||||
pPoll, err := common.Polls.Get(topic.Poll)
|
pPoll, err := common.Polls.Get(topic.Poll)
|
||||||
|
@ -110,7 +115,7 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
|
||||||
|
|
||||||
// Calculate the offset
|
// Calculate the offset
|
||||||
offset, page, lastPage := common.PageOffset(topic.PostCount, page, common.Config.ItemsPerPage)
|
offset, page, lastPage := common.PageOffset(topic.PostCount, page, common.Config.ItemsPerPage)
|
||||||
tpage := common.TopicPage{header, []common.ReplyUser{}, topic, poll, page, lastPage}
|
tpage := common.TopicPage{header, []common.ReplyUser{}, topic, forum, poll, page, lastPage}
|
||||||
|
|
||||||
// Get the replies if we have any...
|
// Get the replies if we have any...
|
||||||
if topic.PostCount > 0 {
|
if topic.PostCount > 0 {
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
<form action='/topic/edit/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}' method="post">
|
<form action='/topic/edit/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}' method="post">
|
||||||
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.IsClosed}} topic_closed_head{{end}}">
|
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.IsClosed}} topic_closed_head{{end}}">
|
||||||
<h1 class='topic_name hide_on_edit' title='{{.Topic.Title}}'>{{.Topic.Title}}</h1>
|
<h1 class='topic_name hide_on_edit' title='{{.Topic.Title}}'>{{.Topic.Title}}</h1>
|
||||||
{{/** TODO: Inline this CSS **/}}
|
<span class="topic_name_forum_sep hide_on_edit"> / </span>
|
||||||
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status.closed_tooltip"}}' aria-label='{{lang "topic.status_closed_aria"}}' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
<a href="{{.Forum.Link}}" class="topic_forum hide_on_edit">{{.Forum.Name}}</a>
|
||||||
{{/** TODO: Does this need to be guarded by a permission? It's only visible in edit mode anyway, which can't be triggered, if they don't have the permission **/}}
|
{{/** TODO: Does this need to be guarded by a permission? It's only visible in edit mode anyway, which can't be triggered, if they don't have the permission **/}}
|
||||||
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}
|
{{if .CurrentUser.Perms.EditTopic}}
|
||||||
|
@ -21,6 +21,9 @@
|
||||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">{{lang "topic.update_button"}}</button>
|
<button name="topic-button" class="formbutton show_on_edit submit_edit">{{lang "topic.update_button"}}</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<span class="topic_view_count hide_on_edit">{{.Topic.ViewCount}}</span>
|
||||||
|
{{/** TODO: Inline this CSS **/}}
|
||||||
|
{{if .Topic.IsClosed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='{{lang "status.closed_tooltip"}}' aria-label='{{lang "topic.status_closed_aria"}}' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -946,6 +946,21 @@ textarea {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topic_block {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.topic_name_forum_sep {
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-right: 6px;
|
||||||
|
line-height: 26px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.topic_forum {
|
||||||
|
line-height: 23px;
|
||||||
|
}
|
||||||
|
.topic_view_count {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.postImage {
|
.postImage {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 240px;
|
max-width: 240px;
|
||||||
|
|
|
@ -516,10 +516,37 @@ button, .formbutton, .panel_right_button {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.colstack {
|
.colstack, .topic_item {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topic_item .topic_name_forum_sep {
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 30px;
|
||||||
|
margin-left: 7px;
|
||||||
|
margin-right: 7px;
|
||||||
|
}
|
||||||
|
.topic_item .topic_forum {
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 31px;
|
||||||
|
color: #dddddd;
|
||||||
|
}
|
||||||
|
.topic_view_count {
|
||||||
|
font-size: 17px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
.topic_view_count:after {
|
||||||
|
content: " views";
|
||||||
|
}
|
||||||
|
.topic_name_input {
|
||||||
|
width: 100%;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
.topic_item .submit_edit {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
.postImage {
|
.postImage {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 320px;
|
max-width: 320px;
|
||||||
|
@ -610,6 +637,44 @@ button, .formbutton, .panel_right_button {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type=checkbox] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
input[type=checkbox] + label {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
margin-bottom: -2px;
|
||||||
|
margin-right: 8px;
|
||||||
|
border: 1px solid rgb(120,120,120);
|
||||||
|
background-color: rgb(90,90,90);
|
||||||
|
padding-top: 1px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
input[type=checkbox]:checked + label .sel {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: rgb(160,160,160);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.poll_option {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.poll_option_text {
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
.poll_buttons {
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
.poll_buttons button {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.add_like:before, .remove_like:before {
|
.add_like:before, .remove_like:before {
|
||||||
content: "{{index .Phrases "topic.plus_one"}}";
|
content: "{{index .Phrases "topic.plus_one"}}";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue