new modtools ux
- don't allow users to select things they shouldn't be able to - hide mod options the user doesn't have access to - highlight options which can be selected - stop counting topics twice when they're clicked on multiple times fix modtools not opening in some cases fix command orders in batch files fix global.js's getExt() reduce boilerplate
This commit is contained in:
parent
6260dbced7
commit
be609b47ce
|
@ -202,20 +202,25 @@ type TopicListSort struct {
|
|||
Ascending bool
|
||||
}
|
||||
|
||||
type QuickTools struct {
|
||||
CanDelete bool
|
||||
CanLock bool
|
||||
CanMove bool
|
||||
}
|
||||
|
||||
type TopicListPage struct {
|
||||
*Header
|
||||
TopicList []*TopicsRow
|
||||
TopicList []TopicsRowMut
|
||||
ForumList []Forum
|
||||
DefaultForum int
|
||||
Sort TopicListSort
|
||||
CanLock bool
|
||||
CanMove bool
|
||||
QuickTools
|
||||
Paginator
|
||||
}
|
||||
|
||||
type ForumPage struct {
|
||||
*Header
|
||||
ItemList []*TopicsRow
|
||||
ItemList []TopicsRowMut
|
||||
Forum *Forum
|
||||
CanLock bool
|
||||
CanMove bool
|
||||
|
|
|
@ -226,9 +226,9 @@ func compileCommons(c *tmpl.CTemplateSet, head, head2 *Header, forumList []Forum
|
|||
return head2
|
||||
}*/
|
||||
|
||||
var topicsList []*TopicsRow
|
||||
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "::1", 1, 0, 1, 1, 0, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil})
|
||||
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, false, false, Paginator{[]int{1}, 1, 1}}
|
||||
var topicsList []TopicsRowMut
|
||||
topicsList = append(topicsList, TopicsRowMut{&TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "::1", 1, 0, 1, 1, 0, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil}, false})
|
||||
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, QuickTools{false, false, false}, Paginator{[]int{1}, 1, 1}}
|
||||
o.Add("topics", "c.TopicListPage", topicListPage)
|
||||
o.Add("topics_mini", "c.TopicListPage", topicListPage)
|
||||
|
||||
|
@ -309,9 +309,9 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
|
|||
ppage := ProfilePage{htitle("User 526"), replyList, *user, 0, 0, false, false, false, false} // TODO: Use the score from user to generate the currentScore and nextScore
|
||||
t.Add("profile", "c.ProfilePage", ppage)
|
||||
|
||||
var topicsList []*TopicsRow
|
||||
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 1, 0, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil})
|
||||
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, false, false, Paginator{[]int{1}, 1, 1}}
|
||||
var topicsList []TopicsRowMut
|
||||
topicsList = append(topicsList, TopicsRowMut{&TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 1, 0, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil}, false})
|
||||
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, QuickTools{false, false, false}, Paginator{[]int{1}, 1, 1}}
|
||||
|
||||
forumItem := BlankForum(1, "general-forum.1", "General Forum", "Where the general stuff happens", true, "all", 0, "", 0)
|
||||
forumPage := ForumPage{htitle("General Forum"), topicsList, forumItem, false, false, Paginator{[]int{1}, 1, 1}}
|
||||
|
@ -538,8 +538,8 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
|
|||
|
||||
t := TItemHold(make(map[string]TItem))
|
||||
|
||||
topicsRow := &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "::1", 1, 0, 1, 0, 1, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil}
|
||||
t.AddStd("topics_topic", "c.TopicsRow", topicsRow)
|
||||
topicsRow := TopicsRowMut{&TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "::1", 1, 0, 1, 0, 1, "classname", 0, "", user2, "", 0, user3, "General", "/forum/general.2", nil}, false}
|
||||
t.AddStd("topics_topic", "c.TopicsRowMut", topicsRow)
|
||||
|
||||
poll := Poll{ID: 1, Type: 0, Options: map[int]string{0: "Nothing", 1: "Something"}, Results: map[int]int{0: 5, 1: 2}, QuickOptions: []PollOption{
|
||||
PollOption{0, "Nothing"},
|
||||
|
|
|
@ -94,6 +94,11 @@ type TopicUser struct {
|
|||
Deletable bool
|
||||
}
|
||||
|
||||
type TopicsRowMut struct {
|
||||
*TopicsRow
|
||||
CanMod bool
|
||||
}
|
||||
|
||||
// TODO: Embed TopicUser to simplify this structure and it's related logic?
|
||||
type TopicsRow struct {
|
||||
ID int
|
||||
|
@ -151,11 +156,17 @@ type WsTopicsRow struct {
|
|||
LastUser *WsJSONUser
|
||||
ForumName string
|
||||
ForumLink string
|
||||
CanMod bool
|
||||
}
|
||||
|
||||
// TODO: Can we get the client side to render the relative times instead?
|
||||
func (r *TopicsRow) WebSockets() *WsTopicsRow {
|
||||
return &WsTopicsRow{r.ID, r.Link, r.Title, r.CreatedBy, r.IsClosed, r.Sticky, r.CreatedAt, r.LastReplyAt, RelativeTime(r.LastReplyAt), r.LastReplyBy, r.LastReplyID, r.ParentID, r.ViewCount, r.PostCount, r.LikeCount, r.AttachCount, r.ClassName, r.Creator.WebSockets(), r.LastUser.WebSockets(), r.ForumName, r.ForumLink}
|
||||
return &WsTopicsRow{r.ID, r.Link, r.Title, r.CreatedBy, r.IsClosed, r.Sticky, r.CreatedAt, r.LastReplyAt, RelativeTime(r.LastReplyAt), r.LastReplyBy, r.LastReplyID, r.ParentID, r.ViewCount, r.PostCount, r.LikeCount, r.AttachCount, r.ClassName, r.Creator.WebSockets(), r.LastUser.WebSockets(), r.ForumName, r.ForumLink, false}
|
||||
}
|
||||
|
||||
// TODO: Can we get the client side to render the relative times instead?
|
||||
func (r *TopicsRow) WebSockets2(canMod bool) *WsTopicsRow {
|
||||
return &WsTopicsRow{r.ID, r.Link, r.Title, r.CreatedBy, r.IsClosed, r.Sticky, r.CreatedAt, r.LastReplyAt, RelativeTime(r.LastReplyAt), r.LastReplyBy, r.LastReplyID, r.ParentID, r.ViewCount, r.PostCount, r.LikeCount, r.AttachCount, r.ClassName, r.Creator.WebSockets(), r.LastUser.WebSockets(), r.ForumName, r.ForumLink, canMod}
|
||||
}
|
||||
|
||||
// TODO: Stop relying on so many struct types?
|
||||
|
|
|
@ -151,6 +151,7 @@ func wsTopicListTick(h *WsHubImpl) error {
|
|||
}
|
||||
|
||||
canSeeRenders := make(map[string][]byte)
|
||||
canSeeLists := make(map[string][]*WsTopicsRow)
|
||||
for name, canSee := range canSeeMap {
|
||||
topicList, forumList, _, err := TopicList.GetListByCanSee(canSee, 1, 0, nil)
|
||||
if err != nil {
|
||||
|
@ -180,6 +181,7 @@ func wsTopicListTick(h *WsHubImpl) error {
|
|||
for i, topicRow := range topicList {
|
||||
wsTopicList[i] = topicRow.WebSockets()
|
||||
}
|
||||
canSeeLists[name] = wsTopicList
|
||||
|
||||
outBytes, err := json.Marshal(&WsTopicList{wsTopicList, 0, tickStart.Unix()})
|
||||
if err != nil {
|
||||
|
@ -191,17 +193,94 @@ func wsTopicListTick(h *WsHubImpl) error {
|
|||
// TODO: Use MessagePack for additional speed?
|
||||
//fmt.Println("writing to the clients")
|
||||
for _, wsUser := range currentWatchers {
|
||||
group := groups[wsUser.User.Group]
|
||||
u := wsUser.User
|
||||
group := groups[u.Group]
|
||||
canSee := make([]byte, len(group.CanSee))
|
||||
for i, item := range group.CanSee {
|
||||
canSee[i] = byte(item)
|
||||
}
|
||||
sCanSee := string(canSee)
|
||||
l := canSeeLists[sCanSee]
|
||||
|
||||
// TODO: Optimise this away for guests?
|
||||
anyMod, anyLock, anyMove, allMod := false, false, false, true
|
||||
var modSet map[int]int
|
||||
if u.IsSuperAdmin {
|
||||
anyMod = true
|
||||
anyLock = true
|
||||
anyMove = true
|
||||
} else {
|
||||
modSet = make(map[int]int, len(l))
|
||||
for i, t := range l {
|
||||
// TODO: Abstract this?
|
||||
fp, err := FPStore.Get(t.ParentID, u.Group)
|
||||
if err == ErrNoRows {
|
||||
fp = BlankForumPerms()
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
var ccanMod, ccanLock, ccanMove bool
|
||||
if fp.Overrides {
|
||||
ccanLock = fp.CloseTopic
|
||||
ccanMove = fp.MoveTopic
|
||||
ccanMod = t.CreatedBy == u.ID || fp.DeleteTopic || ccanLock || ccanMove
|
||||
} else {
|
||||
ccanLock = u.Perms.CloseTopic
|
||||
ccanMove = u.Perms.MoveTopic
|
||||
ccanMod = t.CreatedBy == u.ID || u.Perms.DeleteTopic || ccanLock || ccanMove
|
||||
}
|
||||
if ccanLock {
|
||||
anyLock = true
|
||||
}
|
||||
if ccanMove {
|
||||
anyMove = true
|
||||
}
|
||||
if ccanMod {
|
||||
anyMod = true
|
||||
} else {
|
||||
allMod = false
|
||||
}
|
||||
var v int
|
||||
if ccanMod {
|
||||
v = 1
|
||||
}
|
||||
modSet[i] = v
|
||||
}
|
||||
}
|
||||
|
||||
//fmt.Println("writing to user #", wsUser.User.ID)
|
||||
outBytes := canSeeRenders[string(canSee)]
|
||||
outBytes := canSeeRenders[sCanSee]
|
||||
//fmt.Println("outBytes: ", string(outBytes))
|
||||
err := wsUser.WriteToPageBytes(outBytes, "/topics/")
|
||||
if err == ErrNoneOnPage {
|
||||
//fmt.Println("outBytes[:len(outBytes)-1]: ", string(outBytes[:len(outBytes)-1]))
|
||||
//e := wsUser.WriteToPageBytes(outBytes, "/topics/")
|
||||
//e := wsUser.WriteToPageBytesMulti([][]byte{outBytes[:len(outBytes)-1], []byte(`,"mod":1}`)}, "/topics/")
|
||||
var e error
|
||||
if !anyMod {
|
||||
e = wsUser.WriteToPageBytes(outBytes, "/topics/")
|
||||
} else {
|
||||
var lm []byte
|
||||
if anyLock && anyMove {
|
||||
lm = []byte(`,"lock":1,"move":1}`)
|
||||
} else if anyLock {
|
||||
lm = []byte(`,"lock":1}`)
|
||||
} else if anyMove {
|
||||
lm = []byte(`,"move":1}`)
|
||||
} else {
|
||||
lm = []byte("}")
|
||||
}
|
||||
if allMod {
|
||||
e = wsUser.WriteToPageBytesMulti([][]byte{outBytes[:len(outBytes)-1], []byte(`,"mod":1`), lm}, "/topics/")
|
||||
} else {
|
||||
// TODO: Temporary and inefficient
|
||||
mBytes, err := json.Marshal(modSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e = wsUser.WriteToPageBytesMulti([][]byte{outBytes[:len(outBytes)-1], []byte(`,"mod":`), mBytes, lm}, "/topics/")
|
||||
}
|
||||
}
|
||||
|
||||
if e == ErrNoneOnPage {
|
||||
//fmt.Printf("werr for #%d: %s\n", wsUser.User.ID, err)
|
||||
wsUser.FinalizePage("/topics/", func() {
|
||||
topicListMutex.Lock()
|
||||
|
|
|
@ -221,8 +221,8 @@ function runWebSockets(resume=false) {
|
|||
if(window.location.protocol == "https:") s = "s";
|
||||
conn = new WebSocket("ws"+s+"://" + document.location.host + "/ws/");
|
||||
|
||||
conn.onerror = err => {
|
||||
console.log(err);
|
||||
conn.onerror = e => {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
// TODO: Sync alerts, topic list, etc.
|
||||
|
@ -297,11 +297,26 @@ function runWebSockets(resume=false) {
|
|||
} else if("Topics" in data) {
|
||||
console.log("topic in data");
|
||||
console.log("data",data);
|
||||
// TODO: Handle desyncs more gracefully?
|
||||
// TODO: Send less unneccessary data?
|
||||
let topic = data.Topics[0];
|
||||
if(topic===undefined){
|
||||
console.log("empty topic list");
|
||||
return;
|
||||
}
|
||||
if("mod" in data) {
|
||||
topic.CanMod = data.mod==1 || data.mod[0]==1;
|
||||
if(data.lock==1) {
|
||||
$(".val_lock").each(function(){
|
||||
this.classList.remove("auto_hide");
|
||||
});
|
||||
}
|
||||
if(data.move==1) {
|
||||
$(".val_move").each(function(){
|
||||
this.classList.remove("auto_hide");
|
||||
});
|
||||
}
|
||||
}
|
||||
// TODO: Fix the data race where the function hasn't been loaded yet
|
||||
let renTopic = Tmpl_topics_topic(topic);
|
||||
$(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe");
|
||||
|
@ -347,7 +362,7 @@ function runWebSockets(resume=false) {
|
|||
|
||||
// TODO: Surely, there's a prettier and more elegant way of doing this?
|
||||
function getExt(name) {
|
||||
if(!name.indexOf('.' > -1)) throw("This file doesn't have an extension");
|
||||
if(!name.indexOf('.') > -1) throw("This file doesn't have an extension");
|
||||
return name.split('.').pop();
|
||||
}
|
||||
|
||||
|
@ -439,9 +454,9 @@ function mainInit(){
|
|||
ev.preventDefault();
|
||||
let blocks = document.getElementsByClassName("more_topic_block_active");
|
||||
for(let i=0; i<blocks.length; i++) {
|
||||
let block = blocks[i];
|
||||
block.classList.remove("more_topic_block_active");
|
||||
block.classList.add("more_topic_block_initial");
|
||||
let bl = blocks[i];
|
||||
bl.classList.remove("more_topic_block_active");
|
||||
bl.classList.add("more_topic_block_initial");
|
||||
}
|
||||
$(".ajax_topic_dupe").fadeOut("slow", function(){
|
||||
$(this).remove();
|
||||
|
@ -646,6 +661,7 @@ function mainInit(){
|
|||
});
|
||||
|
||||
bindPage();
|
||||
runInitHook("after_init_bind_page");
|
||||
|
||||
$(".edit_field").click(function(ev) {
|
||||
ev.preventDefault();
|
||||
|
@ -927,6 +943,7 @@ function bindPage() {
|
|||
});
|
||||
|
||||
bindTopic();
|
||||
runHook("end_bind_page")
|
||||
}
|
||||
|
||||
function unbindPage() {
|
||||
|
|
|
@ -151,16 +151,16 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
|||
addInitHook("start_init", () => {
|
||||
addHook("end_bind_topic", () => {
|
||||
|
||||
let changeListener = (files,handler) => {
|
||||
if(files!=null) {
|
||||
files.removeEventListener("change", handler, false);
|
||||
files.addEventListener("change", handler, false);
|
||||
}
|
||||
};
|
||||
let uploadFiles = document.getElementById("upload_files");
|
||||
if(uploadFiles!=null) {
|
||||
uploadFiles.removeEventListener("change", uploadAttachHandler, false);
|
||||
uploadFiles.addEventListener("change", uploadAttachHandler, false);
|
||||
}
|
||||
changeListener(uploadFiles,uploadAttachHandler);
|
||||
let uploadFilesOp = document.getElementById("upload_files_op");
|
||||
if(uploadFilesOp!=null) {
|
||||
uploadFilesOp.removeEventListener("change", uploadAttachHandler2, false);
|
||||
uploadFilesOp.addEventListener("change", uploadAttachHandler2, false);
|
||||
}
|
||||
changeListener(uploadFilesOp,uploadAttachHandler2);
|
||||
bindAttachManager();
|
||||
|
||||
function bindAttachItems() {
|
||||
|
@ -213,6 +213,34 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
|||
bindAttachManager();
|
||||
});
|
||||
|
||||
function addPollInput() {
|
||||
console.log("clicked on pollinputinput");
|
||||
let dataPollInput = $(this).parent().attr("data-pollinput");
|
||||
console.log("dataPollInput",dataPollInput);
|
||||
if(dataPollInput==undefined) return;
|
||||
if(dataPollInput!=(pollInputIndex-1)) return;
|
||||
$(".poll_content_row .formitem").append(Tmpl_topic_c_poll_input({
|
||||
Index: pollInputIndex,
|
||||
Place: phraseBox["topic"]["topic.reply_add_poll_option"].replace("%d",pollInputIndex),
|
||||
}));
|
||||
pollInputIndex++;
|
||||
console.log("new pollInputIndex",pollInputIndex);
|
||||
$(".pollinputinput").off("click");
|
||||
$(".pollinputinput").click(addPollInput);
|
||||
}
|
||||
|
||||
let pollInputIndex = 1;
|
||||
$("#add_poll_button").unbind("click");
|
||||
$("#add_poll_button").click(ev => {
|
||||
ev.preventDefault();
|
||||
$(".poll_content_row").removeClass("auto_hide");
|
||||
$("#has_poll_input").val("1");
|
||||
$(".pollinputinput").click(addPollInput);
|
||||
});
|
||||
});
|
||||
});
|
||||
//addInitHook("after_init_bind_page", () => {
|
||||
addHook("end_bind_page", () => {
|
||||
$(".moderate_link").unbind("click");
|
||||
$(".mod_floater_submit").unbind("click");
|
||||
$(".moderate_link").click(ev => {
|
||||
|
@ -222,6 +250,7 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
|||
$("#topicsItemList,#forumItemList").addClass("topics_moderate");
|
||||
$(".topic_row").each(function(){
|
||||
$(this).click(function(){
|
||||
if(!this.classList.contains("can_mod") || this.classList.contains("topic_selected")) return;
|
||||
selectedTopics.push(parseInt($(this).attr("data-tid"),10));
|
||||
if(selectedTopics.length==1) {
|
||||
var msg = phraseBox["topic_list"]["topic_list.what_to_do_single"];
|
||||
|
@ -279,31 +308,5 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
|||
bulkActionSender(action,selectedTopics,"");
|
||||
});
|
||||
});
|
||||
|
||||
function addPollInput() {
|
||||
console.log("clicked on pollinputinput");
|
||||
let dataPollInput = $(this).parent().attr("data-pollinput");
|
||||
console.log("dataPollInput",dataPollInput);
|
||||
if(dataPollInput==undefined) return;
|
||||
if(dataPollInput!=(pollInputIndex-1)) return;
|
||||
$(".poll_content_row .formitem").append(Tmpl_topic_c_poll_input({
|
||||
Index: pollInputIndex,
|
||||
Place: phraseBox["topic"]["topic.reply_add_poll_option"].replace("%d",pollInputIndex),
|
||||
}));
|
||||
pollInputIndex++;
|
||||
console.log("new pollInputIndex",pollInputIndex);
|
||||
$(".pollinputinput").off("click");
|
||||
$(".pollinputinput").click(addPollInput);
|
||||
}
|
||||
|
||||
let pollInputIndex = 1;
|
||||
$("#add_poll_button").unbind("click");
|
||||
$("#add_poll_button").click(ev => {
|
||||
ev.preventDefault();
|
||||
$(".poll_content_row").removeClass("auto_hide");
|
||||
$("#has_poll_input").val("1");
|
||||
$(".pollinputinput").click(addPollInput);
|
||||
});
|
||||
});
|
||||
});
|
||||
})()
|
|
@ -54,8 +54,14 @@ func ViewForum(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header, s
|
|||
return nil
|
||||
}
|
||||
|
||||
topicList2 := make([]c.TopicsRowMut, len(topicList))
|
||||
canMod := u.Perms.CloseTopic || u.Perms.MoveTopic
|
||||
for i, t := range topicList {
|
||||
topicList2[i] = c.TopicsRowMut{t, t.CreatedBy == u.ID || canMod}
|
||||
}
|
||||
|
||||
//pageList := c.Paginate(page, lastPage, 5)
|
||||
pi := c.ForumPage{h, topicList, forum, u.Perms.CloseTopic, u.Perms.MoveTopic, pagi}
|
||||
pi := c.ForumPage{h, topicList2, forum, u.Perms.CloseTopic, u.Perms.MoveTopic, pagi}
|
||||
tmpl := forum.Tmpl
|
||||
if tmpl == "" {
|
||||
ferr = renderTemplate("forum", w, r, h, pi)
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
"github.com/Azareal/Gosora/common/phrases"
|
||||
)
|
||||
|
||||
func ForumList(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header) c.RouteError {
|
||||
/*skip, rerr := h.Hooks.VhookSkippable("route_forum_list_start", w, r, user, h)
|
||||
func ForumList(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) c.RouteError {
|
||||
/*skip, rerr := h.Hooks.VhookSkippable("route_forum_list_start", w, r, u, h)
|
||||
if skip || rerr != nil {
|
||||
return rerr
|
||||
}*/
|
||||
skip, rerr := c.H_route_forum_list_start_hook(h.Hooks, w, r, user, h)
|
||||
skip, rerr := c.H_route_forum_list_start_hook(h.Hooks, w, r, u, h)
|
||||
if skip || rerr != nil {
|
||||
return rerr
|
||||
}
|
||||
|
@ -24,18 +24,18 @@ func ForumList(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header
|
|||
|
||||
var err error
|
||||
var canSee []int
|
||||
if user.IsSuperAdmin {
|
||||
if u.IsSuperAdmin {
|
||||
canSee, err = c.Forums.GetAllVisibleIDs()
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
} else {
|
||||
group, err := c.Groups.Get(user.Group)
|
||||
g, err := c.Groups.Get(u.Group)
|
||||
if err != nil {
|
||||
log.Printf("Group #%d doesn't exist despite being used by c.User #%d", user.Group, user.ID)
|
||||
return c.LocalError("Something weird happened", w, r, user)
|
||||
log.Printf("Group #%d doesn't exist despite being used by c.User #%d", u.Group, u.ID)
|
||||
return c.LocalError("Something weird happened", w, r, u)
|
||||
}
|
||||
canSee = group.CanSee
|
||||
canSee = g.CanSee
|
||||
}
|
||||
|
||||
var forumList []c.Forum
|
||||
|
|
|
@ -11,13 +11,13 @@ import (
|
|||
p "github.com/Azareal/Gosora/common/phrases"
|
||||
)
|
||||
|
||||
func Forums(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, user, "forums", "forums")
|
||||
func Forums(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, u, "forums", "forums")
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
basePage.Header.AddScript("Sortable-1.4.0/Sortable.min.js")
|
||||
basePage.Header.AddScriptAsync("panel_forums.js")
|
||||
|
@ -52,26 +52,26 @@ func Forums(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
|||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_forums", &pi})
|
||||
}
|
||||
|
||||
func ForumsCreateSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
||||
func ForumsCreateSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
|
||||
fname := r.PostFormValue("name")
|
||||
fdesc := r.PostFormValue("desc")
|
||||
fpreset := c.StripInvalidPreset(r.PostFormValue("preset"))
|
||||
name := r.PostFormValue("name")
|
||||
desc := r.PostFormValue("desc")
|
||||
preset := c.StripInvalidPreset(r.PostFormValue("preset"))
|
||||
factive := r.PostFormValue("active")
|
||||
active := (factive == "on" || factive == "1")
|
||||
|
||||
fid, err := c.Forums.Create(fname, fdesc, active, fpreset)
|
||||
fid, err := c.Forums.Create(name, desc, active, preset)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
err = c.AdminLogs.Create("create", fid, "forum", user.GetIP(), user.ID)
|
||||
err = c.AdminLogs.Create("create", fid, "forum", u.GetIP(), u.ID)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -81,22 +81,22 @@ func ForumsCreateSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.
|
|||
}
|
||||
|
||||
// TODO: Revamp this
|
||||
func ForumsDelete(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, user, "delete_forum", "forums")
|
||||
func ForumsDelete(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, u, "delete_forum", "forums")
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
|
||||
fid, err := strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return c.LocalError("The provided Forum ID is not a valid number.", w, r, user)
|
||||
return c.LocalError("The provided Forum ID is not a valid number.", w, r, u)
|
||||
}
|
||||
forum, err := c.Forums.Get(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("The forum you're trying to delete doesn't exist.", w, r, user)
|
||||
return c.LocalError("The forum you're trying to delete doesn't exist.", w, r, u)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -105,32 +105,32 @@ func ForumsDelete(w http.ResponseWriter, r *http.Request, user *c.User, sfid str
|
|||
youSure := c.AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid), confirmMsg}
|
||||
|
||||
pi := c.PanelPage{basePage, tList, youSure}
|
||||
if c.RunPreRenderHook("pre_render_panel_delete_forum", w, r, user, &pi) {
|
||||
if c.RunPreRenderHook("pre_render_panel_delete_forum", w, r, u, &pi) {
|
||||
return nil
|
||||
}
|
||||
return renderTemplate("panel_are_you_sure", w, r, basePage.Header, &pi)
|
||||
}
|
||||
|
||||
func ForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
||||
func ForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
|
||||
fid, err := strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return c.LocalError("The provided Forum ID is not a valid number.", w, r, user)
|
||||
return c.LocalError("The provided Forum ID is not a valid number.", w, r, u)
|
||||
}
|
||||
err = c.Forums.Delete(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("The forum you're trying to delete doesn't exist.", w, r, user)
|
||||
return c.LocalError("The forum you're trying to delete doesn't exist.", w, r, u)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
err = c.AdminLogs.Create("delete", fid, "forum", user.GetIP(), user.ID)
|
||||
err = c.AdminLogs.Create("delete", fid, "forum", u.GetIP(), u.ID)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -139,14 +139,14 @@ func ForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sf
|
|||
return nil
|
||||
}
|
||||
|
||||
func ForumsOrderSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
||||
func ForumsOrderSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
js := r.PostFormValue("js") == "1"
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissionsJSQ(w, r, user, js)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissionsJSQ(w, r, u, js)
|
||||
}
|
||||
sitems := strings.TrimSuffix(strings.TrimPrefix(r.PostFormValue("items"), "{"), "}")
|
||||
//fmt.Printf("sitems: %+v\n", sitems)
|
||||
|
@ -155,13 +155,13 @@ func ForumsOrderSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.R
|
|||
for index, sfid := range strings.Split(sitems, ",") {
|
||||
fid, err := strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return c.LocalErrorJSQ("Invalid integer in forum list", w, r, user, js)
|
||||
return c.LocalErrorJSQ("Invalid integer in forum list", w, r, u, js)
|
||||
}
|
||||
updateMap[fid] = index
|
||||
}
|
||||
c.Forums.UpdateOrder(updateMap)
|
||||
|
||||
err := c.AdminLogs.Create("reorder", 0, "forum", user.GetIP(), user.ID)
|
||||
err := c.AdminLogs.Create("reorder", 0, "forum", u.GetIP(), u.ID)
|
||||
if err != nil {
|
||||
return c.InternalErrorJSQ(err, w, r, js)
|
||||
}
|
||||
|
@ -169,13 +169,13 @@ func ForumsOrderSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.R
|
|||
return successRedirect("/panel/forums/", w, r, js)
|
||||
}
|
||||
|
||||
func ForumsEdit(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, user, "edit_forum", "forums")
|
||||
func ForumsEdit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, u, "edit_forum", "forums")
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
|
||||
fid, err := strconv.Atoi(sfid)
|
||||
|
@ -186,7 +186,7 @@ func ForumsEdit(w http.ResponseWriter, r *http.Request, user *c.User, sfid strin
|
|||
|
||||
forum, err := c.Forums.Get(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("The forum you're trying to edit doesn't exist.", w, r, user)
|
||||
return c.LocalError("The forum you're trying to edit doesn't exist.", w, r, u)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -222,30 +222,30 @@ func ForumsEdit(w http.ResponseWriter, r *http.Request, user *c.User, sfid strin
|
|||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_forum_edit", &pi})
|
||||
}
|
||||
|
||||
func ForumsEditSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
||||
func ForumsEditSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
js := r.PostFormValue("js") == "1"
|
||||
|
||||
fid, err := strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return c.LocalErrorJSQ("The provided Forum ID is not a valid number.", w, r, user, js)
|
||||
return c.LocalErrorJSQ("The provided Forum ID is not a valid number.", w, r, u, js)
|
||||
}
|
||||
forum, err := c.Forums.Get(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalErrorJSQ("The forum you're trying to edit doesn't exist.", w, r, user, js)
|
||||
return c.LocalErrorJSQ("The forum you're trying to edit doesn't exist.", w, r, u, js)
|
||||
} else if err != nil {
|
||||
return c.InternalErrorJSQ(err, w, r, js)
|
||||
}
|
||||
|
||||
fname := r.PostFormValue("forum_name")
|
||||
fdesc := r.PostFormValue("forum_desc")
|
||||
fpreset := c.StripInvalidPreset(r.PostFormValue("forum_preset"))
|
||||
name := r.PostFormValue("forum_name")
|
||||
desc := r.PostFormValue("forum_desc")
|
||||
preset := c.StripInvalidPreset(r.PostFormValue("forum_preset"))
|
||||
factive := r.PostFormValue("forum_active")
|
||||
|
||||
active := false
|
||||
|
@ -255,11 +255,11 @@ func ForumsEditSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid
|
|||
active = true
|
||||
}
|
||||
|
||||
err = forum.Update(fname, fdesc, active, fpreset)
|
||||
err = forum.Update(name, desc, active, preset)
|
||||
if err != nil {
|
||||
return c.InternalErrorJSQ(err, w, r, js)
|
||||
}
|
||||
err = c.AdminLogs.Create("edit", fid, "forum", user.GetIP(), user.ID)
|
||||
err = c.AdminLogs.Create("edit", fid, "forum", u.GetIP(), u.ID)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -268,29 +268,28 @@ func ForumsEditSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid
|
|||
return successRedirect("/panel/forums/", w, r, js)
|
||||
}
|
||||
|
||||
func ForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
||||
func ForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
js := r.PostFormValue("js") == "1"
|
||||
|
||||
fid, err := strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return c.LocalErrorJSQ("The provided Forum ID is not a valid number.", w, r, user, js)
|
||||
return c.LocalErrorJSQ("The provided Forum ID is not a valid number.", w, r, u, js)
|
||||
}
|
||||
|
||||
gid, err := strconv.Atoi(r.PostFormValue("gid"))
|
||||
if err != nil {
|
||||
return c.LocalErrorJSQ("Invalid Group ID", w, r, user, js)
|
||||
return c.LocalErrorJSQ("Invalid Group ID", w, r, u, js)
|
||||
}
|
||||
|
||||
forum, err := c.Forums.Get(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalErrorJSQ("This forum doesn't exist", w, r, user, js)
|
||||
return c.LocalErrorJSQ("This forum doesn't exist", w, r, u, js)
|
||||
} else if err != nil {
|
||||
return c.InternalErrorJSQ(err, w, r, js)
|
||||
}
|
||||
|
@ -298,9 +297,9 @@ func ForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user *c.User,
|
|||
permPreset := c.StripInvalidGroupForumPreset(r.PostFormValue("perm_preset"))
|
||||
err = forum.SetPreset(permPreset, gid)
|
||||
if err != nil {
|
||||
return c.LocalErrorJSQ(err.Error(), w, r, user, js)
|
||||
return c.LocalErrorJSQ(err.Error(), w, r, u, js)
|
||||
}
|
||||
err = c.AdminLogs.Create("edit", fid, "forum", user.GetIP(), user.ID)
|
||||
err = c.AdminLogs.Create("edit", fid, "forum", u.GetIP(), u.ID)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -328,23 +327,23 @@ func forumPermsExtractDash(paramList string) (fid, gid int, err error) {
|
|||
return fid, gid, err
|
||||
}
|
||||
|
||||
func ForumsEditPermsAdvance(w http.ResponseWriter, r *http.Request, user *c.User, paramList string) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, user, "edit_forum", "forums")
|
||||
func ForumsEditPermsAdvance(w http.ResponseWriter, r *http.Request, u *c.User, paramList string) c.RouteError {
|
||||
basePage, ferr := buildBasePage(w, r, u, "edit_forum", "forums")
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
|
||||
fid, gid, err := forumPermsExtractDash(paramList)
|
||||
if err != nil {
|
||||
return c.LocalError(err.Error(), w, r, user)
|
||||
return c.LocalError(err.Error(), w, r, u)
|
||||
}
|
||||
|
||||
f, err := c.Forums.Get(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("The forum you're trying to edit doesn't exist.", w, r, user)
|
||||
return c.LocalError("The forum you're trying to edit doesn't exist.", w, r, u)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -386,24 +385,24 @@ func ForumsEditPermsAdvance(w http.ResponseWriter, r *http.Request, user *c.User
|
|||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "", "", "panel_forum_edit_perms", &pi})
|
||||
}
|
||||
|
||||
func ForumsEditPermsAdvanceSubmit(w http.ResponseWriter, r *http.Request, user *c.User, paramList string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
||||
func ForumsEditPermsAdvanceSubmit(w http.ResponseWriter, r *http.Request, u *c.User, paramList string) c.RouteError {
|
||||
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, user)
|
||||
if !u.Perms.ManageForums {
|
||||
return c.NoPermissions(w, r, u)
|
||||
}
|
||||
js := r.PostFormValue("js") == "1"
|
||||
|
||||
fid, gid, err := forumPermsExtractDash(paramList)
|
||||
if err != nil {
|
||||
return c.LocalError(err.Error(), w, r, user)
|
||||
return c.LocalError(err.Error(), w, r, u)
|
||||
}
|
||||
|
||||
forum, err := c.Forums.Get(fid)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("The forum you're trying to edit doesn't exist.", w, r, user)
|
||||
return c.LocalError("The forum you're trying to edit doesn't exist.", w, r, u)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -435,9 +434,9 @@ func ForumsEditPermsAdvanceSubmit(w http.ResponseWriter, r *http.Request, user *
|
|||
|
||||
err = forum.SetPerms(&fp, "custom", gid)
|
||||
if err != nil {
|
||||
return c.LocalErrorJSQ(err.Error(), w, r, user, js)
|
||||
return c.LocalErrorJSQ(err.Error(), w, r, u, js)
|
||||
}
|
||||
err = c.AdminLogs.Create("edit", fid, "forum", user.GetIP(), user.ID)
|
||||
err = c.AdminLogs.Create("edit", fid, "forum", u.GetIP(), u.ID)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,21 @@ func wsTopicList(topicList []*c.TopicsRow, lastPage int) *c.WsTopicList {
|
|||
return &c.WsTopicList{wsTopicList, lastPage, 0}
|
||||
}
|
||||
|
||||
func wsTopicList2(topicList []*c.TopicsRow, u *c.User, fps map[int]c.QuickTools, lastPage int) *c.WsTopicList {
|
||||
wsTopicList := make([]*c.WsTopicsRow, len(topicList))
|
||||
for i, t := range topicList {
|
||||
var canMod bool
|
||||
if fps == nil {
|
||||
canMod = true
|
||||
} else {
|
||||
quickTools := fps[t.ParentID]
|
||||
canMod = t.CreatedBy == u.ID || quickTools.CanDelete || quickTools.CanLock || quickTools.CanMove
|
||||
}
|
||||
wsTopicList[i] = t.WebSockets2(canMod)
|
||||
}
|
||||
return &c.WsTopicList{wsTopicList, lastPage, 0}
|
||||
}
|
||||
|
||||
func TopicList(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header) c.RouteError {
|
||||
/*skip, rerr := h.Hooks.VhookSkippable("route_topic_list_start", w, r, u, h)
|
||||
if skip || rerr != nil {
|
||||
|
@ -79,7 +94,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
|||
var topicList []*c.TopicsRow
|
||||
var forumList []c.Forum
|
||||
var pagi c.Paginator
|
||||
var canLock, ccanLock, canMove, ccanMove bool
|
||||
var canDelete, ccanDelete, canLock, ccanLock, canMove, ccanMove bool
|
||||
q := r.FormValue("q")
|
||||
if q != "" && c.RepliesSearch != nil {
|
||||
var canSee []int
|
||||
|
@ -152,35 +167,46 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
|||
|
||||
// TODO: De-dupe this logic in common/topic_list.go?
|
||||
//var sb strings.Builder
|
||||
fps := make(map[int]c.QuickTools)
|
||||
for _, t := range topicList {
|
||||
//c.BuildTopicURLSb(&sb, c.NameToSlug(t.Title), t.ID)
|
||||
//t.Link = sb.String()
|
||||
//sb.Reset()
|
||||
t.Link = c.BuildTopicURL(c.NameToSlug(t.Title), t.ID)
|
||||
// TODO: Pass forum to something like t.Forum and use that instead of these two properties? Could be more flexible.
|
||||
forum := c.Forums.DirtyGet(t.ParentID)
|
||||
t.ForumName = forum.Name
|
||||
t.ForumLink = forum.Link
|
||||
f := c.Forums.DirtyGet(t.ParentID)
|
||||
t.ForumName = f.Name
|
||||
t.ForumLink = f.Link
|
||||
|
||||
fp, err := c.FPStore.Get(forum.ID, user.Group)
|
||||
_, ok := fps[f.ID]
|
||||
if !ok {
|
||||
// TODO: Abstract this?
|
||||
fp, err := c.FPStore.Get(f.ID, user.Group)
|
||||
if err == c.ErrNoRows {
|
||||
fp = c.BlankForumPerms()
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
if fp.Overrides && !user.IsSuperAdmin {
|
||||
ccanDelete = fp.DeleteTopic
|
||||
ccanLock = fp.CloseTopic
|
||||
ccanMove = fp.MoveTopic
|
||||
} else {
|
||||
ccanDelete = user.Perms.DeleteTopic
|
||||
ccanLock = user.Perms.CloseTopic
|
||||
ccanMove = user.Perms.MoveTopic
|
||||
}
|
||||
if ccanDelete {
|
||||
canDelete = true
|
||||
}
|
||||
if ccanLock {
|
||||
canLock = true
|
||||
}
|
||||
if ccanMove {
|
||||
canMove = true
|
||||
}
|
||||
fps[f.ID] = c.QuickTools{ccanDelete, ccanLock, ccanMove}
|
||||
}
|
||||
|
||||
// TODO: Create a specialised function with a bit less overhead for getting the last page for a post count
|
||||
_, _, lastPage := c.PageOffset(t.PostCount, 1, c.Config.ItemsPerPage)
|
||||
|
@ -192,7 +218,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
|||
|
||||
// TODO: Reduce the amount of boilerplate here
|
||||
if r.FormValue("js") == "1" {
|
||||
outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON()
|
||||
outBytes, err := wsTopicList2(topicList, user, fps, pagi.LastPage).MarshalJSON()
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -200,37 +226,57 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
|||
return nil
|
||||
}
|
||||
|
||||
topicList2 := make([]c.TopicsRowMut, len(topicList))
|
||||
for i, t := range topicList {
|
||||
var canMod bool
|
||||
if fps == nil {
|
||||
canMod = true
|
||||
} else {
|
||||
quickTools := fps[t.ParentID]
|
||||
canMod = t.CreatedBy == user.ID || quickTools.CanDelete || quickTools.CanLock || quickTools.CanMove
|
||||
}
|
||||
topicList2[i] = c.TopicsRowMut{t, canMod}
|
||||
}
|
||||
|
||||
h.Title = phrases.GetTitlePhrase("topics_search")
|
||||
pi := c.TopicListPage{h, topicList, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, canLock, canMove, pagi}
|
||||
pi := c.TopicListPage{h, topicList2, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, c.QuickTools{canDelete, canLock, canMove}, pagi}
|
||||
return renderTemplate("topics", w, r, h, pi)
|
||||
}
|
||||
|
||||
// TODO: Pass a struct back rather than passing back so many variables
|
||||
var fps map[int]c.QuickTools
|
||||
if user.IsSuperAdmin {
|
||||
topicList, forumList, pagi, err = c.TopicList.GetList(page, tsorder, fids)
|
||||
canLock, canMove = true, true
|
||||
} else {
|
||||
topicList, forumList, pagi, err = c.TopicList.GetListByGroup(group, page, tsorder, fids)
|
||||
for _, forum := range forumList {
|
||||
fp, err := c.FPStore.Get(forum.ID, user.Group)
|
||||
fps = make(map[int]c.QuickTools)
|
||||
for _, f := range forumList {
|
||||
fp, err := c.FPStore.Get(f.ID, user.Group)
|
||||
if err == c.ErrNoRows {
|
||||
fp = c.BlankForumPerms()
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
if fp.Overrides {
|
||||
ccanDelete = fp.DeleteTopic
|
||||
ccanLock = fp.CloseTopic
|
||||
ccanMove = fp.MoveTopic
|
||||
} else {
|
||||
ccanDelete = user.Perms.DeleteTopic
|
||||
ccanLock = user.Perms.CloseTopic
|
||||
ccanMove = user.Perms.MoveTopic
|
||||
}
|
||||
if ccanDelete {
|
||||
canDelete = true
|
||||
}
|
||||
if ccanLock {
|
||||
canLock = true
|
||||
}
|
||||
if ccanMove {
|
||||
canMove = true
|
||||
}
|
||||
fps[f.ID] = c.QuickTools{ccanDelete, ccanLock, ccanMove}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -239,7 +285,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
|||
|
||||
// TODO: Reduce the amount of boilerplate here
|
||||
if r.FormValue("js") == "1" {
|
||||
outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON()
|
||||
outBytes, err := wsTopicList2(topicList, user, fps, pagi.LastPage).MarshalJSON()
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -247,7 +293,19 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
|||
return nil
|
||||
}
|
||||
|
||||
pi := c.TopicListPage{h, topicList, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, canLock, canMove, pagi}
|
||||
topicList2 := make([]c.TopicsRowMut, len(topicList))
|
||||
for i, t := range topicList {
|
||||
var canMod bool
|
||||
if fps == nil {
|
||||
canMod = true
|
||||
} else {
|
||||
quickTools := fps[t.ParentID]
|
||||
canMod = t.CreatedBy == user.ID || quickTools.CanDelete || quickTools.CanLock || quickTools.CanMove
|
||||
}
|
||||
topicList2[i] = c.TopicsRowMut{t, canMod}
|
||||
}
|
||||
|
||||
pi := c.TopicListPage{h, topicList2, forumList, c.Config.DefaultForum, c.TopicListSort{torder, false}, c.QuickTools{canDelete, canLock, canMove}, pagi}
|
||||
if r.FormValue("i") == "1" {
|
||||
return renderTemplate("topics_mini", w, r, h, pi)
|
||||
}
|
||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the hook generator
|
||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the query generator
|
||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the hook generator
|
||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the query generator
|
||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the hook generator
|
||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the query generator
|
||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the hook generator
|
||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
|||
exit /b %errorlevel%
|
||||
)
|
||||
|
||||
echo Generating the JSON handlers
|
||||
easyjson -pkg common
|
||||
|
||||
echo Building the query generator
|
||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||
if %errorlevel% neq 0 (
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
{{end}}
|
||||
{{end}}
|
||||
<div id="forum_topic_list"class="rowblock topic_list single_forum"aria-label="{{lang "forum_list_aria"}}">
|
||||
{{range .ItemList}}<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}"data-tid="{{.ID}}">
|
||||
{{range .ItemList}}<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}{{if .CanMod}} can_mod{{end}}"data-tid="{{.ID}}">
|
||||
<div class="rowitem topic_left passive datarow">
|
||||
<span class="selector"></span>
|
||||
<a href="{{.Creator.Link}}"><img src="{{.Creator.MicroAvatar}}"height=64 alt="Avatar"title="{{.Creator.Name}}'s Avatar"aria-hidden="true"></a>
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
</div>
|
||||
<div class="mod_floater_body">
|
||||
<select class="mod_floater_options">
|
||||
<option value="delete">{{lang "topic_list.moderate_delete"}}</option>
|
||||
{{if .CanLock}}<option value="lock">{{lang "topic_list.moderate_lock"}}</option>{{end}}
|
||||
{{if .CanMove}}<option value="move">{{lang "topic_list.moderate_move"}}</option>{{end}}
|
||||
<option class="val_delete" value="delete">{{lang "topic_list.moderate_delete"}}</option>
|
||||
<option class="val_lock{{if not .CanLock}} auto_hide{{end}}" value="lock">{{lang "topic_list.moderate_lock"}}</option>
|
||||
<option class="val_move{{if not .CanMove}} auto_hide{{end}}" value="move">{{lang "topic_list.moderate_move"}}</option>
|
||||
</select>
|
||||
<button class="mod_floater_submit">{{lang "topic_list.moderate_run"}}</button>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}" data-tid="{{.ID}}">
|
||||
<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}{{if .CanMod}} can_mod{{end}}" data-tid="{{.ID}}">
|
||||
<div class="rowitem topic_left passive datarow">
|
||||
<span class="selector"></span>
|
||||
<a href="{{.Creator.Link}}"><img src="{{.Creator.MicroAvatar}}"height=64 alt="Avatar"title="{{.Creator.Name}}'s Avatar"aria-hidden="true"></a>
|
||||
|
|
|
@ -907,7 +907,11 @@ textarea {
|
|||
.topic_sticky .topic_left, .topic_sticky .topic_right {
|
||||
border-bottom: 2px solid hsl(51, 60%, 70%);
|
||||
}
|
||||
.topics_moderate .topic_row:hover .topic_left, .topics_moderate .topic_row:hover .topic_right {
|
||||
.topics_moderate .topic_row:not(.can_mod) .topic_left,
|
||||
.topics_moderate .topic_row:not(.can_mod) .topic_right {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
.topics_moderate .can_mod:hover .topic_left, .topics_moderate .can_mod:hover .topic_right {
|
||||
background-color: hsl(81, 60%, 97%);
|
||||
}
|
||||
.topic_selected .topic_left, .topic_selected .topic_right {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}"data-tid={{.ID}}>
|
||||
<div class="topic_row{{if .Sticky}} topic_sticky{{else if .IsClosed}} topic_closed{{end}}{{if .CanMod}} can_mod{{end}}"data-tid={{.ID}}>
|
||||
<div class="rowitem topic_left passive datarow">
|
||||
<a href="{{.Creator.Link}}"><img src="{{.Creator.MicroAvatar}}"height=64 alt="Avatar"title="{{.Creator.Name}}'s Avatar"aria-hidden="true"></a>
|
||||
<span class="topic_inner_left">
|
||||
|
|
|
@ -228,7 +228,10 @@ li a {
|
|||
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem, .sidebar .search {
|
||||
margin-left: 12px;
|
||||
}
|
||||
.topics_moderate .topic_row:hover {
|
||||
.topics_moderate .can_mod {
|
||||
background-color: #4d4d4d;
|
||||
}
|
||||
.topics_moderate .can_mod:hover {
|
||||
background-color: rgb(78, 78, 98);
|
||||
}
|
||||
.widget_search:first-child {
|
||||
|
@ -552,7 +555,7 @@ h2 {
|
|||
.topic_closed {
|
||||
background-color: #4b4b4b;
|
||||
}
|
||||
.topic_selected {
|
||||
.topic_row.topic_selected {
|
||||
background-color: rgb(68, 68, 88);
|
||||
}
|
||||
.new_item .topic_left {
|
||||
|
|
|
@ -855,12 +855,18 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
|
|||
.topic_list .topic_row {
|
||||
display: flex;
|
||||
}
|
||||
.topics_moderate .topic_row:hover .rowitem {
|
||||
background-color: hsla(0, 0%, 27%, 1);
|
||||
.topics_moderate .topic_row:not(.can_mod) .rowitem {
|
||||
background-color: hsla(0, 0%, 22%, 1);
|
||||
}
|
||||
.topic_selected .rowitem {
|
||||
.topics_moderate .can_mod .rowitem {
|
||||
background-color: hsla(0, 0%, 25%, 1);
|
||||
}
|
||||
.topics_moderate .can_mod:hover .rowitem {
|
||||
background-color: hsla(0, 0%, 29%, 1);
|
||||
}
|
||||
.topic_row.topic_selected .rowitem {
|
||||
background-color: hsla(0, 0%, 31%, 1);
|
||||
}
|
||||
/* Temporary hack, so that I don't break the topic lists of the other themes */
|
||||
.topic_list .topic_inner_right {
|
||||
display: none;
|
||||
|
|
Loading…
Reference in New Issue