\n"))
for i := 0; i <= pageCount; i++ {
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)
if err != nil {
- log.Print("The guest group doesn't exist for some reason")
- // TODO: Add XML error handling to errors.go
- w.WriteHeader(500)
- w.Write(xmlInternalError)
- return common.HandledRouteError()
+ return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
}
- var argList []interface{}
- var qlist string
+ var visibleForums []common.Forum
for _, fid := range group.CanSee {
forum := common.Forums.DirtyGet(fid)
if forum.Name != "" && forum.Active {
- argList = append(argList, strconv.Itoa(fid))
- qlist += "?,"
+ visibleForums = append(visibleForums, forum.Copy())
}
}
- if qlist != "" {
- qlist = qlist[0 : len(qlist)-1]
- }
- // TODO: Abstract this
- topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
+ argList, qlist := common.ForumListToArgQ(visibleForums)
+ topicCount, err := common.ArgQToTopicCount(argList, qlist)
if err != nil {
- // TODO: Add XML error handling to errors.go
- 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()
+ return common.InternalErrorXML(err, w, r)
}
var pageCount = topicCount / sitemapPageCap
diff --git a/common/errors.go b/common/errors.go
index cc1ad568..79f39ce6 100644
--- a/common/errors.go
+++ b/common/errors.go
@@ -99,6 +99,26 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteErr
return HandledRouteError()
}
+var xmlInternalError = []byte(`
+A problem has occured`)
+
+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 {
w.WriteHeader(500)
pi := Page{"Error", GuestUser, DefaultHeaderVar(), tList, errmsg}
diff --git a/common/forum_store.go b/common/forum_store.go
index d9177e8b..fb75e931 100644
--- a/common/forum_store.go
+++ b/common/forum_store.go
@@ -27,6 +27,7 @@ type ForumStore interface {
DirtyGet(id int) *Forum
Get(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
//Update(Forum) error
Delete(id int) error
@@ -188,6 +189,19 @@ func (mfs *MemoryForumStore) BypassGet(id int) (*Forum, error) {
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 {
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)
diff --git a/common/parser.go b/common/parser.go
index 52b86ee9..ff051c16 100644
--- a/common/parser.go
+++ b/common/parser.go
@@ -165,10 +165,10 @@ func shortcodeToUnicode(msg string) string {
}
func PreparseMessage(msg string) string {
- msg = strings.Replace(msg, "
", "\n", -1)
- msg = strings.Replace(msg, "
", "\n", -1)
+ msg = strings.Replace(msg, "
", "\n\n", -1)
+ msg = strings.Replace(msg, "
", "\n\n", -1)
msg = strings.Replace(msg, "
", "", -1)
- msg = strings.Replace(msg, "
", "\n", -1)
+ msg = strings.Replace(msg, "
", "\n\n", -1)
if Sshooks["preparse_preassign"] != nil {
msg = RunSshook("preparse_preassign", msg)
}
diff --git a/common/topic_list.go b/common/topic_list.go
new file mode 100644
index 00000000..b6282417
--- /dev/null
+++ b/common/topic_list.go
@@ -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))
+}
diff --git a/routes.go b/routes.go
index e8b00891..1cfdfb01 100644
--- a/routes.go
+++ b/routes.go
@@ -135,8 +135,6 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo
headerVars.Zone = "topics"
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)
if err != nil {
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
var forumList []common.Forum
- var argList []interface{}
-
for _, fid := range canSee {
forum := common.Forums.DirtyGet(fid)
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
+ // ? - Would it be useful, if we could post in social groups from /topics/?
if (forum.ParentType == "" || forum.ParentType == "forum") && user.Loggedin {
fcopy := forum.Copy()
// TODO: Add a hook here for plugin_guilds
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
if qlist == "" {
return common.NotFound(w, r)
}
- qlist = qlist[0 : len(qlist)-1]
- // TODO: Abstract this
- 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)
+ topicCount, err := common.ArgQToTopicCount(argList, qlist)
if err != nil {
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 {
return ferr
}
-
if !user.Perms.ViewTopic {
return common.NoPermissions(w, r, user)
}
diff --git a/themes/cosora/public/main.css b/themes/cosora/public/main.css
index b57df627..f4e73676 100644
--- a/themes/cosora/public/main.css
+++ b/themes/cosora/public/main.css
@@ -580,11 +580,10 @@ select, input, textarea, button {
display: inline-block;
}
.topic_list .rowtopic span {
- max-width: 112px;
+ max-width: 162px;
overflow: hidden;
color: var(--primary-text-color);
}
-
.topic_list .rowsmall {
font-size: 15px;
}
@@ -596,17 +595,9 @@ select, input, textarea, button {
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 {
font-size: 14px;
}
-
.topic_list .topic_status_e {
display: none;
}
@@ -615,7 +606,6 @@ select, input, textarea, button {
flex: 1 1 calc(100% - 380px);
border-right: none;
}
-
.topic_inner_right {
margin-left: 15%;
margin-right: auto;
@@ -633,12 +623,9 @@ select, input, textarea, button {
.topic_inner_right {
margin-top: 12px;
}
-
.topic_inner_right span {
- /*font-size: 15px;*/
font-size: 16px;
}
-
.topic_inner_right span:after {
font-size: 13.5px;
}
@@ -656,7 +643,6 @@ select, input, textarea, button {
content: var(--likes-lang-string);
color: var(--lightened-primary-text-color);
}
-
.parent_forum {
color: var(--lightened-primary-text-color);
}
@@ -684,7 +670,7 @@ select, input, textarea, button {
margin-top: 12px;
margin-left: 8px;
margin-bottom: 14px;
- width: 240px;
+ width: 220px;
}
.topic_right > span {
margin-top: 12px;
@@ -698,7 +684,7 @@ select, input, textarea, button {
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 {
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 {
border: none;
}
@@ -778,6 +776,9 @@ select, input, textarea, button {
.userinfo .tag_block {
color: var(--extra-lightened-primary-text-color);
}
+.post_item .user_content {
+ margin-bottom: 10px;
+}
.button_container {
margin-top: auto;
display: flex;
diff --git a/themes/cosora/public/panel.css b/themes/cosora/public/panel.css
index 8ad5abc3..f5248a38 100644
--- a/themes/cosora/public/panel.css
+++ b/themes/cosora/public/panel.css
@@ -77,10 +77,41 @@
.formlist .formitem {
padding: 8px;
}
-#forum_quick_perms .panel_floater,
.panel_theme_mobile, .panel_theme_tag {
display: none;
}
#panel_plugins .rowitem {
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";
}
\ No newline at end of file