Added the Update method to *Forum and fixed a bug where forum updates would bypass the forumView cache.
Fixed a bug in MemoryForumStore's CacheSet where it requires new entries to exist, even though they don't need to. Fixed a bug where the Reports could be deleted. Fixed a bug in the JS where the inline forum editor stopped working. Fixed a bug in Shadow where the Add Group header was pushed to the side by the previous element's margin. Fixed a bug in the Forum Editor where the Active input's initial value was inverted.
This commit is contained in:
parent
b955f677a7
commit
f5d5f755bb
23
forum.go
23
forum.go
|
@ -1,8 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
//import "fmt"
|
//import "fmt"
|
||||||
import "strconv"
|
import (
|
||||||
import _ "github.com/go-sql-driver/mysql"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
type ForumAdmin struct {
|
type ForumAdmin struct {
|
||||||
ID int
|
ID int
|
||||||
|
@ -39,6 +43,21 @@ type ForumSimple struct {
|
||||||
Preset string
|
Preset string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (forum *Forum) Update(name string, desc string, active bool, preset string) error {
|
||||||
|
if name == "" {
|
||||||
|
name = forum.Name
|
||||||
|
}
|
||||||
|
preset = strings.TrimSpace(preset)
|
||||||
|
_, err := updateForumStmt.Exec(name, desc, active, preset, forum.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if forum.Preset != preset || preset == "custom" || preset == "" {
|
||||||
|
permmapToQuery(presetToPermmap(preset), forum.ID)
|
||||||
|
}
|
||||||
|
_ = fstore.Reload(forum.ID)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Replace this sorting mechanism with something a lot more efficient
|
// TODO: Replace this sorting mechanism with something a lot more efficient
|
||||||
// ? - Use sort.Slice instead?
|
// ? - Use sort.Slice instead?
|
||||||
type SortForum []*Forum
|
type SortForum []*Forum
|
||||||
|
|
|
@ -8,6 +8,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -28,7 +29,7 @@ type ForumStore interface {
|
||||||
Get(id int) (*Forum, error)
|
Get(id int) (*Forum, error)
|
||||||
GetCopy(id int) (Forum, error)
|
GetCopy(id int) (Forum, error)
|
||||||
BypassGet(id int) (*Forum, error)
|
BypassGet(id int) (*Forum, error)
|
||||||
Reload(id int) error // ? - Should we move this to TopicCache? Might require us to do a lot more casting in Gosora 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
|
||||||
IncrementTopicCount(id int) error
|
IncrementTopicCount(id int) error
|
||||||
|
@ -216,9 +217,6 @@ func (mfs *MemoryForumStore) Reload(id int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) CacheSet(forum *Forum) error {
|
func (mfs *MemoryForumStore) CacheSet(forum *Forum) error {
|
||||||
if !mfs.Exists(forum.ID) {
|
|
||||||
return ErrNoRows
|
|
||||||
}
|
|
||||||
mfs.forums.Store(forum.ID, forum)
|
mfs.forums.Store(forum.ID, forum)
|
||||||
mfs.rebuildView()
|
mfs.rebuildView()
|
||||||
return nil
|
return nil
|
||||||
|
@ -278,7 +276,11 @@ func (mfs *MemoryForumStore) CacheDelete(id int) {
|
||||||
mfs.rebuildView()
|
mfs.rebuildView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add a hook to allow plugin_socialgroups to detect when one of it's forums has just been deleted?
|
||||||
func (mfs *MemoryForumStore) Delete(id int) error {
|
func (mfs *MemoryForumStore) Delete(id int) error {
|
||||||
|
if id == 1 {
|
||||||
|
return errors.New("You cannot delete the Reports forum")
|
||||||
|
}
|
||||||
forumUpdateMutex.Lock()
|
forumUpdateMutex.Lock()
|
||||||
defer forumUpdateMutex.Unlock()
|
defer forumUpdateMutex.Unlock()
|
||||||
_, err := mfs.delete.Exec(id)
|
_, err := mfs.delete.Exec(id)
|
||||||
|
|
|
@ -417,11 +417,6 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
forumName := r.PostFormValue("forum_name")
|
|
||||||
forumDesc := r.PostFormValue("forum_desc")
|
|
||||||
forumPreset := stripInvalidPreset(r.PostFormValue("forum_preset"))
|
|
||||||
forumActive := r.PostFormValue("forum_active")
|
|
||||||
|
|
||||||
forum, err := fstore.Get(fid)
|
forum, err := fstore.Get(fid)
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
LocalErrorJSQ("The forum you're trying to edit doesn't exist.", w, r, user, isJs)
|
LocalErrorJSQ("The forum you're trying to edit doesn't exist.", w, r, user, isJs)
|
||||||
|
@ -431,40 +426,23 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if forumName == "" {
|
forumName := r.PostFormValue("forum_name")
|
||||||
forumName = forum.Name
|
forumDesc := r.PostFormValue("forum_desc")
|
||||||
}
|
forumPreset := stripInvalidPreset(r.PostFormValue("forum_preset"))
|
||||||
|
forumActive := r.PostFormValue("forum_active")
|
||||||
|
|
||||||
var active bool
|
var active = false
|
||||||
if forumActive == "" {
|
if forumActive == "" {
|
||||||
active = forum.Active
|
active = forum.Active
|
||||||
} else if forumActive == "1" || forumActive == "Show" {
|
} else if forumActive == "1" || forumActive == "Show" {
|
||||||
active = true
|
active = true
|
||||||
} else {
|
|
||||||
active = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forumUpdateMutex.Lock()
|
err = forum.Update(forumName, forumDesc, active, forumPreset)
|
||||||
_, err = updateForumStmt.Exec(forumName, forumDesc, active, forumPreset, fid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalErrorJSQ(err, w, r, isJs)
|
InternalErrorJSQ(err, w, r, isJs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if forum.Name != forumName {
|
|
||||||
forum.Name = forumName
|
|
||||||
}
|
|
||||||
if forum.Desc != forumDesc {
|
|
||||||
forum.Desc = forumDesc
|
|
||||||
}
|
|
||||||
if forum.Active != active {
|
|
||||||
forum.Active = active
|
|
||||||
}
|
|
||||||
if forum.Preset != forumPreset {
|
|
||||||
forum.Preset = forumPreset
|
|
||||||
}
|
|
||||||
forumUpdateMutex.Unlock()
|
|
||||||
|
|
||||||
permmapToQuery(presetToPermmap(forumPreset), fid)
|
|
||||||
|
|
||||||
if !isJs {
|
if !isJs {
|
||||||
http.Redirect(w, r, "/panel/forums/", http.StatusSeeOther)
|
http.Redirect(w, r, "/panel/forums/", http.StatusSeeOther)
|
||||||
|
@ -473,6 +451,7 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ! This probably misses the forumView cache
|
||||||
func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user User, sfid string) {
|
func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user User, sfid string) {
|
||||||
_, ok := SimplePanelUserCheck(w, r, &user)
|
_, ok := SimplePanelUserCheck(w, r, &user)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -305,11 +305,12 @@ $(document).ready(function(){
|
||||||
//console.log("Field Type",field_type)
|
//console.log("Field Type",field_type)
|
||||||
//console.log("Field Value '" + field_value + "'")
|
//console.log("Field Value '" + field_value + "'")
|
||||||
for (var i = 0; i < itLen; i++) {
|
for (var i = 0; i < itLen; i++) {
|
||||||
|
var sel = "";
|
||||||
if(field_value == i || field_value == it[i]) {
|
if(field_value == i || field_value == it[i]) {
|
||||||
sel = "selected ";
|
sel = "selected ";
|
||||||
this.classList.remove(field_name + '_' + it[i]);
|
this.classList.remove(field_name + '_' + it[i]);
|
||||||
this.innerHTML = "";
|
this.innerHTML = "";
|
||||||
} else sel = "";
|
}
|
||||||
out += "<option "+sel+"value='"+i+"'>"+it[i]+"</option>";
|
out += "<option "+sel+"value='"+i+"'>"+it[i]+"</option>";
|
||||||
}
|
}
|
||||||
this.innerHTML = "<select data-field='"+field_name+"' name='"+field_name+"'>"+out+"</select>";
|
this.innerHTML = "<select data-field='"+field_name+"' name='"+field_name+"'>"+out+"</select>";
|
||||||
|
|
|
@ -21,8 +21,8 @@ var form_vars = {'perm_preset': ['can_moderate','can_post','read_only','no_acces
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>Active</a></div>
|
<div class="formitem formlabel"><a>Active</a></div>
|
||||||
<div class="formitem"><select name="forum_active">
|
<div class="formitem"><select name="forum_active">
|
||||||
<option{{if not .Active}} selected{{end}} value="1">Yes</option>
|
<option{{if .Active}} selected{{end}} value="1">Yes</option>
|
||||||
<option{{if .Active}} selected{{end}} value="0">No</option>
|
<option{{if not .Active}} selected{{end}} value="0">No</option>
|
||||||
</select></div>
|
</select></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
<form action="/panel/forums/create/?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/forums/create/?session={{.CurrentUser.Session}}" method="post">
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>Forum Name</a></div>
|
<div class="formitem formlabel"><a>Name</a></div>
|
||||||
<div class="formitem"><input name="forum-name" type="text" placeholder="Super Secret Forum" /></div>
|
<div class="formitem"><input name="forum-name" type="text" placeholder="Super Secret Forum" /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>Active</a></div>
|
<div class="formitem formlabel"><a>Active</a></div>
|
||||||
<div class="formitem"><select name="forum-active">
|
<div class="formitem"><select name="forum-active">
|
||||||
<option value="1">Yes</option>
|
<option selected value="1">Yes</option>
|
||||||
<option value="0">No</option>
|
<option value="0">No</option>
|
||||||
</select></div>
|
</select></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -393,15 +393,14 @@ textarea.large {
|
||||||
/* Mini paginators aka panel paginators */
|
/* Mini paginators aka panel paginators */
|
||||||
.pageset {
|
.pageset {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
clear: both;
|
display: flex;
|
||||||
height: 32px;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.pageitem {
|
.pageitem {
|
||||||
background-color: rgb(61,61,61);
|
background-color: rgb(61,61,61);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
float: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.rowlist.bgavatars .rowitem {
|
.rowlist.bgavatars .rowitem {
|
||||||
|
|
5
user.go
5
user.go
|
@ -107,7 +107,7 @@ func (user *User) RevertGroupUpdate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use a transaction here
|
// TODO: Use a transaction here
|
||||||
// TODO: Add a Deactivate method?
|
// ? - Add a Deactivate method? Not really needed, if someone's been bad you could do a ban, I guess it might be useful, if someone says that email x isn't actually owned by the user in question?
|
||||||
func (user *User) Activate() (err error) {
|
func (user *User) Activate() (err error) {
|
||||||
_, err = activateUserStmt.Exec(user.ID)
|
_, err = activateUserStmt.Exec(user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -201,6 +201,7 @@ func (user *User) decreasePostStats(wcount int, topic bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Write unit tests for this
|
||||||
func (user *User) initPerms() {
|
func (user *User) initPerms() {
|
||||||
if user.TempGroup != 0 {
|
if user.TempGroup != 0 {
|
||||||
user.Group = user.TempGroup
|
user.Group = user.TempGroup
|
||||||
|
@ -272,6 +273,7 @@ func SendValidationEmail(username string, email string, token string) bool {
|
||||||
return SendEmail(email, subject, msg)
|
return SendEmail(email, subject, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Write units tests for this
|
||||||
func wordsToScore(wcount int, topic bool) (score int) {
|
func wordsToScore(wcount int, topic bool) (score int) {
|
||||||
if topic {
|
if topic {
|
||||||
score = 2
|
score = 2
|
||||||
|
@ -288,6 +290,7 @@ func wordsToScore(wcount int, topic bool) (score int) {
|
||||||
return score
|
return score
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Write unit tests for this
|
||||||
func buildProfileURL(slug string, uid int) string {
|
func buildProfileURL(slug string, uid int) string {
|
||||||
if slug == "" {
|
if slug == "" {
|
||||||
return "/user/" + strconv.Itoa(uid)
|
return "/user/" + strconv.Itoa(uid)
|
||||||
|
|
Loading…
Reference in New Issue