Fixed the forum editor on Cosora. More excavating coming up.

Tweaked the preparser to hopefully fix a few problems with the WYSIWYG Editor.
Added BulkGetCopy to the ForumStores.
Added InternalErrorXML and SilentInternalErrorXML.
Tweaked the element queries so that the topic titles aren't truncated too short.

Began refactoring the topic list logic, more to come here.
This commit is contained in:
Azareal 2017-12-26 07:17:26 +00:00
parent e919812ee2
commit 21999cd7c6
8 changed files with 141 additions and 109 deletions

View File

@ -1,13 +1,13 @@
package main package main
import ( import (
"errors"
"log" "log"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"./common" "./common"
"./query_gen/lib"
) )
// TODO: Make this a static file somehow? Is it possible for us to put this file somewhere else? // TODO: Make this a static file somehow? Is it possible for us to put this file somewhere else?
@ -23,8 +23,6 @@ Disallow: /report/
return nil return nil
} }
var xmlInternalError = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<error>A problem has occured</error>`)
var sitemapPageCap = 40000 // 40k, bump it up to 50k once we gzip this? Does brotli work on sitemaps? var sitemapPageCap = 40000 // 40k, bump it up to 50k once we gzip this? Does brotli work on sitemaps?
func writeXMLHeader(w http.ResponseWriter, r *http.Request) { func writeXMLHeader(w http.ResponseWriter, r *http.Request) {
@ -110,11 +108,7 @@ func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteErro
group, err := common.Groups.Get(common.GuestUser.Group) group, err := common.Groups.Get(common.GuestUser.Group)
if err != nil { if err != nil {
log.Print("The guest group doesn't exist for some reason") return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
// TODO: Add XML error handling to errors.go
w.WriteHeader(500)
w.Write(xmlInternalError)
return common.HandledRouteError()
} }
writeXMLHeader(w, r) writeXMLHeader(w, r)
@ -145,54 +139,29 @@ func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteErro
</sitemap> </sitemap>
`)) `))
} }
writeXMLHeader(w, r)
group, err := common.Groups.Get(common.GuestUser.Group) group, err := common.Groups.Get(common.GuestUser.Group)
if err != nil { if err != nil {
log.Print("The guest group doesn't exist for some reason") return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
// TODO: Add XML error handling to errors.go
w.WriteHeader(500)
w.Write(xmlInternalError)
return common.HandledRouteError()
} }
var argList []interface{} var visibleForums []common.Forum
var qlist string
for _, fid := range group.CanSee { for _, fid := range group.CanSee {
forum := common.Forums.DirtyGet(fid) forum := common.Forums.DirtyGet(fid)
if forum.Name != "" && forum.Active { if forum.Name != "" && forum.Active {
argList = append(argList, strconv.Itoa(fid)) visibleForums = append(visibleForums, forum.Copy())
qlist += "?,"
} }
} }
if qlist != "" {
qlist = qlist[0 : len(qlist)-1]
}
// TODO: Abstract this topicCount, err := common.TopicCountInForums(visibleForums)
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
if err != nil { if err != nil {
// TODO: Add XML error handling to errors.go return common.InternalErrorXML(err, w, r)
w.WriteHeader(500)
w.Write(xmlInternalError)
common.LogError(err)
return common.HandledRouteError()
}
defer topicCountStmt.Close()
var topicCount int
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
if err != nil && err != ErrNoRows {
// TODO: Add XML error handling to errors.go
w.WriteHeader(500)
w.Write(xmlInternalError)
common.LogError(err)
return common.HandledRouteError()
} }
var pageCount = topicCount / sitemapPageCap var pageCount = topicCount / sitemapPageCap
//log.Print("topicCount", topicCount) //log.Print("topicCount", topicCount)
//log.Print("pageCount", pageCount) //log.Print("pageCount", pageCount)
writeXMLHeader(w, r)
w.Write([]byte("<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n")) w.Write([]byte("<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n"))
for i := 0; i <= pageCount; i++ { for i := 0; i <= pageCount; i++ {
sitemapItem("sitemaps/topics_page_" + strconv.Itoa(i) + ".xml") sitemapItem("sitemaps/topics_page_" + strconv.Itoa(i) + ".xml")
@ -215,45 +184,21 @@ func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common.
group, err := common.Groups.Get(common.GuestUser.Group) group, err := common.Groups.Get(common.GuestUser.Group)
if err != nil { if err != nil {
log.Print("The guest group doesn't exist for some reason") return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
// TODO: Add XML error handling to errors.go
w.WriteHeader(500)
w.Write(xmlInternalError)
return common.HandledRouteError()
} }
var argList []interface{} var visibleForums []common.Forum
var qlist string
for _, fid := range group.CanSee { for _, fid := range group.CanSee {
forum := common.Forums.DirtyGet(fid) forum := common.Forums.DirtyGet(fid)
if forum.Name != "" && forum.Active { if forum.Name != "" && forum.Active {
argList = append(argList, strconv.Itoa(fid)) visibleForums = append(visibleForums, forum.Copy())
qlist += "?,"
} }
} }
if qlist != "" {
qlist = qlist[0 : len(qlist)-1]
}
// TODO: Abstract this argList, qlist := common.ForumListToArgQ(visibleForums)
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "") topicCount, err := common.ArgQToTopicCount(argList, qlist)
if err != nil { if err != nil {
// TODO: Add XML error handling to errors.go return common.InternalErrorXML(err, w, r)
w.WriteHeader(500)
w.Write(xmlInternalError)
common.LogError(err)
return common.HandledRouteError()
}
defer topicCountStmt.Close()
var topicCount int
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
if err != nil && err != ErrNoRows {
// TODO: Add XML error handling to errors.go
w.WriteHeader(500)
w.Write(xmlInternalError)
common.LogError(err)
return common.HandledRouteError()
} }
var pageCount = topicCount / sitemapPageCap var pageCount = topicCount / sitemapPageCap

View File

@ -99,6 +99,26 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteErr
return HandledRouteError() return HandledRouteError()
} }
var xmlInternalError = []byte(`<?xml version="1.0" encoding="UTF-8"?>
<error>A problem has occured</error>`)
func InternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteError {
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(500)
w.Write(xmlInternalError)
LogError(err)
return HandledRouteError()
}
// TODO: Stop killing the instance upon hitting an error with InternalError* and deprecate this
func SilentInternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteError {
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(500)
w.Write(xmlInternalError)
log.Print("InternalError: ", err)
return HandledRouteError()
}
func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError { func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError {
w.WriteHeader(500) w.WriteHeader(500)
pi := Page{"Error", GuestUser, DefaultHeaderVar(), tList, errmsg} pi := Page{"Error", GuestUser, DefaultHeaderVar(), tList, errmsg}

View File

@ -27,6 +27,7 @@ type ForumStore interface {
DirtyGet(id int) *Forum DirtyGet(id int) *Forum
Get(id int) (*Forum, error) Get(id int) (*Forum, error)
BypassGet(id int) (*Forum, error) BypassGet(id int) (*Forum, error)
BulkGetCopy(ids []int) (forums []Forum, err error)
Reload(id int) error // ? - Should we move this to ForumCache? It might require us to do some unnecessary casting though Reload(id int) error // ? - Should we move this to ForumCache? It might require us to do some unnecessary casting though
//Update(Forum) error //Update(Forum) error
Delete(id int) error Delete(id int) error
@ -188,6 +189,19 @@ func (mfs *MemoryForumStore) BypassGet(id int) (*Forum, error) {
return forum, err return forum, err
} }
// TODO: Optimise this
func (mfs *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error) {
forums = make([]Forum, len(ids))
for i, id := range ids {
forum, err := mfs.Get(id)
if err != nil {
return nil, err
}
forums[i] = forum.Copy()
}
return forums, nil
}
func (mfs *MemoryForumStore) Reload(id int) error { func (mfs *MemoryForumStore) Reload(id int) error {
var forum = &Forum{ID: id} var forum = &Forum{ID: id}
err := mfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID) err := mfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)

View File

@ -165,10 +165,10 @@ func shortcodeToUnicode(msg string) string {
} }
func PreparseMessage(msg string) string { func PreparseMessage(msg string) string {
msg = strings.Replace(msg, "<p><br>", "\n", -1) msg = strings.Replace(msg, "<p><br>", "\n\n", -1)
msg = strings.Replace(msg, "<p>", "\n", -1) msg = strings.Replace(msg, "<p>", "\n\n", -1)
msg = strings.Replace(msg, "</p>", "", -1) msg = strings.Replace(msg, "</p>", "", -1)
msg = strings.Replace(msg, "<br>", "\n", -1) msg = strings.Replace(msg, "<br>", "\n\n", -1)
if Sshooks["preparse_preassign"] != nil { if Sshooks["preparse_preassign"] != nil {
msg = RunSshook("preparse_preassign", msg) msg = RunSshook("preparse_preassign", msg)
} }

35
common/topic_list.go Normal file
View File

@ -0,0 +1,35 @@
package common
import "strconv"
import "../query_gen/lib"
// Internal. Don't rely on it.
func ForumListToArgQ(forums []Forum) (argList []interface{}, qlist string) {
for _, forum := range forums {
argList = append(argList, strconv.Itoa(forum.ID))
qlist += "?,"
}
if qlist != "" {
qlist = qlist[0 : len(qlist)-1]
}
return argList, qlist
}
// Internal. Don't rely on it.
func ArgQToTopicCount(argList []interface{}, qlist string) (topicCount int, err error) {
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
if err != nil {
return 0, err
}
defer topicCountStmt.Close()
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
if err != nil && err != ErrNoRows {
return 0, err
}
return topicCount, err
}
func TopicCountInForums(forums []Forum) (topicCount int, err error) {
return ArgQToTopicCount(ForumListToArgQ(forums))
}

View File

@ -135,8 +135,6 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo
headerVars.Zone = "topics" headerVars.Zone = "topics"
headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string) headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string)
// TODO: Add a function for the qlist stuff
var qlist string
group, err := common.Groups.Get(user.Group) group, err := common.Groups.Get(user.Group)
if err != nil { if err != nil {
log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID) log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID)
@ -156,39 +154,28 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo
// We need a list of the visible forums for Quick Topic // We need a list of the visible forums for Quick Topic
var forumList []common.Forum var forumList []common.Forum
var argList []interface{}
for _, fid := range canSee { for _, fid := range canSee {
forum := common.Forums.DirtyGet(fid) forum := common.Forums.DirtyGet(fid)
if forum.Name != "" && forum.Active { if forum.Name != "" && forum.Active {
// This bit's for quick topic, as we don't want unbound forums (e.g. ones in plugin_socialgroups) showing up // This bit's for quick topic, as we don't want unbound forums (e.g. ones in plugin_socialgroups) showing up
// ? - Would it be useful, if we could post in social groups from /topics/?
if (forum.ParentType == "" || forum.ParentType == "forum") && user.Loggedin { if (forum.ParentType == "" || forum.ParentType == "forum") && user.Loggedin {
fcopy := forum.Copy() fcopy := forum.Copy()
// TODO: Add a hook here for plugin_guilds // TODO: Add a hook here for plugin_guilds
forumList = append(forumList, fcopy) forumList = append(forumList, fcopy)
} }
// ? - Should we be showing plugin_guilds posts on /topics/?
// ? - Would it be useful, if we could post in social groups from /topics/?
argList = append(argList, strconv.Itoa(fid))
qlist += "?,"
} }
} }
// ? - Should we be showing plugin_guilds posts on /topics/?
argList, qlist := common.ForumListToArgQ(forumList)
// ! Need an inline error not a page level error // ! Need an inline error not a page level error
if qlist == "" { if qlist == "" {
return common.NotFound(w, r) return common.NotFound(w, r)
} }
qlist = qlist[0 : len(qlist)-1]
// TODO: Abstract this topicCount, err := common.ArgQToTopicCount(argList, qlist)
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
if err != nil {
return common.InternalError(err, w, r)
}
defer topicCountStmt.Close()
var topicCount int
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }
@ -304,7 +291,6 @@ func routeForum(w http.ResponseWriter, r *http.Request, user common.User, sfid s
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
if !user.Perms.ViewTopic { if !user.Perms.ViewTopic {
return common.NoPermissions(w, r, user) return common.NoPermissions(w, r, user)
} }

View File

@ -580,11 +580,10 @@ select, input, textarea, button {
display: inline-block; display: inline-block;
} }
.topic_list .rowtopic span { .topic_list .rowtopic span {
max-width: 112px; max-width: 162px;
overflow: hidden; overflow: hidden;
color: var(--primary-text-color); color: var(--primary-text-color);
} }
.topic_list .rowsmall { .topic_list .rowsmall {
font-size: 15px; font-size: 15px;
} }
@ -596,17 +595,9 @@ select, input, textarea, button {
font-size: 15px; font-size: 15px;
} }
.topic_list .rowsmall.starter:before {
content: "\f007";
font: normal normal normal 14px/1 FontAwesome;
margin-right: 5px;
font-size: 15px;
}
.topic_list .lastReplyAt { .topic_list .lastReplyAt {
font-size: 14px; font-size: 14px;
} }
.topic_list .topic_status_e { .topic_list .topic_status_e {
display: none; display: none;
} }
@ -615,7 +606,6 @@ select, input, textarea, button {
flex: 1 1 calc(100% - 380px); flex: 1 1 calc(100% - 380px);
border-right: none; border-right: none;
} }
.topic_inner_right { .topic_inner_right {
margin-left: 15%; margin-left: 15%;
margin-right: auto; margin-right: auto;
@ -633,12 +623,9 @@ select, input, textarea, button {
.topic_inner_right { .topic_inner_right {
margin-top: 12px; margin-top: 12px;
} }
.topic_inner_right span { .topic_inner_right span {
/*font-size: 15px;*/
font-size: 16px; font-size: 16px;
} }
.topic_inner_right span:after { .topic_inner_right span:after {
font-size: 13.5px; font-size: 13.5px;
} }
@ -656,7 +643,6 @@ select, input, textarea, button {
content: var(--likes-lang-string); content: var(--likes-lang-string);
color: var(--lightened-primary-text-color); color: var(--lightened-primary-text-color);
} }
.parent_forum { .parent_forum {
color: var(--lightened-primary-text-color); color: var(--lightened-primary-text-color);
} }
@ -684,7 +670,7 @@ select, input, textarea, button {
margin-top: 12px; margin-top: 12px;
margin-left: 8px; margin-left: 8px;
margin-bottom: 14px; margin-bottom: 14px;
width: 240px; width: 220px;
} }
.topic_right > span { .topic_right > span {
margin-top: 12px; margin-top: 12px;
@ -698,7 +684,7 @@ select, input, textarea, button {
background-color: hsl(81, 60%, 95%); background-color: hsl(81, 60%, 95%);
} }
@element .topic_left .rowtopic and (min-width: 110px) { @element .topic_left .rowtopic and (min-width: 160px) {
$this, $this span, $this + .parent_forum { $this, $this span, $this + .parent_forum {
float: left; float: left;
} }
@ -712,6 +698,18 @@ select, input, textarea, button {
} }
} }
@element .topic_list and (min-width: 738px) {
.topic_left .topic_inner_left {
width: calc(240px + 1%);
}
}
@element .topic_list and (min-width: 875px) {
.topic_left .topic_inner_left {
width: calc(240px + 10%);
}
}
.forum_list, .post_container { .forum_list, .post_container {
border: none; border: none;
} }
@ -778,6 +776,9 @@ select, input, textarea, button {
.userinfo .tag_block { .userinfo .tag_block {
color: var(--extra-lightened-primary-text-color); color: var(--extra-lightened-primary-text-color);
} }
.post_item .user_content {
margin-bottom: 10px;
}
.button_container { .button_container {
margin-top: auto; margin-top: auto;
display: flex; display: flex;

View File

@ -77,10 +77,41 @@
.formlist .formitem { .formlist .formitem {
padding: 8px; padding: 8px;
} }
#forum_quick_perms .panel_floater,
.panel_theme_mobile, .panel_theme_tag { .panel_theme_mobile, .panel_theme_tag {
display: none; display: none;
} }
#panel_plugins .rowitem { #panel_plugins .rowitem {
display: block; display: block;
}
#forum_quick_perms .formitem {
display: flex;
}
#forum_quick_perms .formitem .edit_fields {
margin-left: 3px;
margin-top: 1px;
}
.perm_preset_no_access:before {
content: "No Access";
color: hsl(0,100%,20%);
}
.perm_preset_read_only:before, .perm_preset_can_post:before {
color: hsl(120,100%,20%);
}
.perm_preset_read_only:before {
content: "Read Only";
}
.perm_preset_can_post:before {
content: "Can Post";
}
.perm_preset_can_moderate:before {
content: "Can Moderate";
color: hsl(240,100%,20%);
}
.perm_preset_custom:before {
content: "Custom";
color: hsl(0,0%,20%);
}
.perm_preset_default:before {
content: "Default";
} }