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
|
Ascending bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type QuickTools struct {
|
||||||
|
CanDelete bool
|
||||||
|
CanLock bool
|
||||||
|
CanMove bool
|
||||||
|
}
|
||||||
|
|
||||||
type TopicListPage struct {
|
type TopicListPage struct {
|
||||||
*Header
|
*Header
|
||||||
TopicList []*TopicsRow
|
TopicList []TopicsRowMut
|
||||||
ForumList []Forum
|
ForumList []Forum
|
||||||
DefaultForum int
|
DefaultForum int
|
||||||
Sort TopicListSort
|
Sort TopicListSort
|
||||||
CanLock bool
|
QuickTools
|
||||||
CanMove bool
|
|
||||||
Paginator
|
Paginator
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForumPage struct {
|
type ForumPage struct {
|
||||||
*Header
|
*Header
|
||||||
ItemList []*TopicsRow
|
ItemList []TopicsRowMut
|
||||||
Forum *Forum
|
Forum *Forum
|
||||||
CanLock bool
|
CanLock bool
|
||||||
CanMove bool
|
CanMove bool
|
||||||
|
|
|
@ -226,9 +226,9 @@ func compileCommons(c *tmpl.CTemplateSet, head, head2 *Header, forumList []Forum
|
||||||
return head2
|
return head2
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
var topicsList []*TopicsRow
|
var topicsList []TopicsRowMut
|
||||||
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})
|
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}, false, false, Paginator{[]int{1}, 1, 1}}
|
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", "c.TopicListPage", topicListPage)
|
||||||
o.Add("topics_mini", "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
|
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)
|
t.Add("profile", "c.ProfilePage", ppage)
|
||||||
|
|
||||||
var topicsList []*TopicsRow
|
var topicsList []TopicsRowMut
|
||||||
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})
|
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}, false, false, Paginator{[]int{1}, 1, 1}}
|
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)
|
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}}
|
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))
|
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}
|
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.TopicsRow", topicsRow)
|
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{
|
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"},
|
PollOption{0, "Nothing"},
|
||||||
|
|
|
@ -94,6 +94,11 @@ type TopicUser struct {
|
||||||
Deletable bool
|
Deletable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TopicsRowMut struct {
|
||||||
|
*TopicsRow
|
||||||
|
CanMod bool
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Embed TopicUser to simplify this structure and it's related logic?
|
// TODO: Embed TopicUser to simplify this structure and it's related logic?
|
||||||
type TopicsRow struct {
|
type TopicsRow struct {
|
||||||
ID int
|
ID int
|
||||||
|
@ -151,11 +156,17 @@ type WsTopicsRow struct {
|
||||||
LastUser *WsJSONUser
|
LastUser *WsJSONUser
|
||||||
ForumName string
|
ForumName string
|
||||||
ForumLink string
|
ForumLink string
|
||||||
|
CanMod bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Can we get the client side to render the relative times instead?
|
// TODO: Can we get the client side to render the relative times instead?
|
||||||
func (r *TopicsRow) WebSockets() *WsTopicsRow {
|
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?
|
// TODO: Stop relying on so many struct types?
|
||||||
|
|
|
@ -151,6 +151,7 @@ func wsTopicListTick(h *WsHubImpl) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
canSeeRenders := make(map[string][]byte)
|
canSeeRenders := make(map[string][]byte)
|
||||||
|
canSeeLists := make(map[string][]*WsTopicsRow)
|
||||||
for name, canSee := range canSeeMap {
|
for name, canSee := range canSeeMap {
|
||||||
topicList, forumList, _, err := TopicList.GetListByCanSee(canSee, 1, 0, nil)
|
topicList, forumList, _, err := TopicList.GetListByCanSee(canSee, 1, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -180,6 +181,7 @@ func wsTopicListTick(h *WsHubImpl) error {
|
||||||
for i, topicRow := range topicList {
|
for i, topicRow := range topicList {
|
||||||
wsTopicList[i] = topicRow.WebSockets()
|
wsTopicList[i] = topicRow.WebSockets()
|
||||||
}
|
}
|
||||||
|
canSeeLists[name] = wsTopicList
|
||||||
|
|
||||||
outBytes, err := json.Marshal(&WsTopicList{wsTopicList, 0, tickStart.Unix()})
|
outBytes, err := json.Marshal(&WsTopicList{wsTopicList, 0, tickStart.Unix()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -191,17 +193,94 @@ func wsTopicListTick(h *WsHubImpl) error {
|
||||||
// TODO: Use MessagePack for additional speed?
|
// TODO: Use MessagePack for additional speed?
|
||||||
//fmt.Println("writing to the clients")
|
//fmt.Println("writing to the clients")
|
||||||
for _, wsUser := range currentWatchers {
|
for _, wsUser := range currentWatchers {
|
||||||
group := groups[wsUser.User.Group]
|
u := wsUser.User
|
||||||
|
group := groups[u.Group]
|
||||||
canSee := make([]byte, len(group.CanSee))
|
canSee := make([]byte, len(group.CanSee))
|
||||||
for i, item := range group.CanSee {
|
for i, item := range group.CanSee {
|
||||||
canSee[i] = byte(item)
|
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)
|
//fmt.Println("writing to user #", wsUser.User.ID)
|
||||||
outBytes := canSeeRenders[string(canSee)]
|
outBytes := canSeeRenders[sCanSee]
|
||||||
//fmt.Println("outBytes: ", string(outBytes))
|
//fmt.Println("outBytes: ", string(outBytes))
|
||||||
err := wsUser.WriteToPageBytes(outBytes, "/topics/")
|
//fmt.Println("outBytes[:len(outBytes)-1]: ", string(outBytes[:len(outBytes)-1]))
|
||||||
if err == ErrNoneOnPage {
|
//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)
|
//fmt.Printf("werr for #%d: %s\n", wsUser.User.ID, err)
|
||||||
wsUser.FinalizePage("/topics/", func() {
|
wsUser.FinalizePage("/topics/", func() {
|
||||||
topicListMutex.Lock()
|
topicListMutex.Lock()
|
||||||
|
|
|
@ -221,8 +221,8 @@ function runWebSockets(resume=false) {
|
||||||
if(window.location.protocol == "https:") s = "s";
|
if(window.location.protocol == "https:") s = "s";
|
||||||
conn = new WebSocket("ws"+s+"://" + document.location.host + "/ws/");
|
conn = new WebSocket("ws"+s+"://" + document.location.host + "/ws/");
|
||||||
|
|
||||||
conn.onerror = err => {
|
conn.onerror = e => {
|
||||||
console.log(err);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Sync alerts, topic list, etc.
|
// TODO: Sync alerts, topic list, etc.
|
||||||
|
@ -297,11 +297,26 @@ function runWebSockets(resume=false) {
|
||||||
} else if("Topics" in data) {
|
} else if("Topics" in data) {
|
||||||
console.log("topic in data");
|
console.log("topic in data");
|
||||||
console.log("data",data);
|
console.log("data",data);
|
||||||
|
// TODO: Handle desyncs more gracefully?
|
||||||
|
// TODO: Send less unneccessary data?
|
||||||
let topic = data.Topics[0];
|
let topic = data.Topics[0];
|
||||||
if(topic===undefined){
|
if(topic===undefined){
|
||||||
console.log("empty topic list");
|
console.log("empty topic list");
|
||||||
return;
|
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
|
// TODO: Fix the data race where the function hasn't been loaded yet
|
||||||
let renTopic = Tmpl_topics_topic(topic);
|
let renTopic = Tmpl_topics_topic(topic);
|
||||||
$(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe");
|
$(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe");
|
||||||
|
@ -313,7 +328,7 @@ function runWebSockets(resume=false) {
|
||||||
moreTopicCount++;
|
moreTopicCount++;
|
||||||
|
|
||||||
let blocks = document.getElementsByClassName("more_topic_block_initial");
|
let blocks = document.getElementsByClassName("more_topic_block_initial");
|
||||||
for(let i=0; i < blocks.length; i++) {
|
for(let i=0; i<blocks.length; i++) {
|
||||||
let block = blocks[i];
|
let block = blocks[i];
|
||||||
block.classList.remove("more_topic_block_initial");
|
block.classList.remove("more_topic_block_initial");
|
||||||
block.classList.add("more_topic_block_active");
|
block.classList.add("more_topic_block_active");
|
||||||
|
@ -347,7 +362,7 @@ function runWebSockets(resume=false) {
|
||||||
|
|
||||||
// TODO: Surely, there's a prettier and more elegant way of doing this?
|
// TODO: Surely, there's a prettier and more elegant way of doing this?
|
||||||
function getExt(name) {
|
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();
|
return name.split('.').pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,9 +454,9 @@ function mainInit(){
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
let blocks = document.getElementsByClassName("more_topic_block_active");
|
let blocks = document.getElementsByClassName("more_topic_block_active");
|
||||||
for(let i=0; i<blocks.length; i++) {
|
for(let i=0; i<blocks.length; i++) {
|
||||||
let block = blocks[i];
|
let bl = blocks[i];
|
||||||
block.classList.remove("more_topic_block_active");
|
bl.classList.remove("more_topic_block_active");
|
||||||
block.classList.add("more_topic_block_initial");
|
bl.classList.add("more_topic_block_initial");
|
||||||
}
|
}
|
||||||
$(".ajax_topic_dupe").fadeOut("slow", function(){
|
$(".ajax_topic_dupe").fadeOut("slow", function(){
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
|
@ -646,6 +661,7 @@ function mainInit(){
|
||||||
});
|
});
|
||||||
|
|
||||||
bindPage();
|
bindPage();
|
||||||
|
runInitHook("after_init_bind_page");
|
||||||
|
|
||||||
$(".edit_field").click(function(ev) {
|
$(".edit_field").click(function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
@ -927,6 +943,7 @@ function bindPage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
bindTopic();
|
bindTopic();
|
||||||
|
runHook("end_bind_page")
|
||||||
}
|
}
|
||||||
|
|
||||||
function unbindPage() {
|
function unbindPage() {
|
||||||
|
|
153
public/member.js
153
public/member.js
|
@ -151,16 +151,16 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
||||||
addInitHook("start_init", () => {
|
addInitHook("start_init", () => {
|
||||||
addHook("end_bind_topic", () => {
|
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");
|
let uploadFiles = document.getElementById("upload_files");
|
||||||
if(uploadFiles!=null) {
|
changeListener(uploadFiles,uploadAttachHandler);
|
||||||
uploadFiles.removeEventListener("change", uploadAttachHandler, false);
|
|
||||||
uploadFiles.addEventListener("change", uploadAttachHandler, false);
|
|
||||||
}
|
|
||||||
let uploadFilesOp = document.getElementById("upload_files_op");
|
let uploadFilesOp = document.getElementById("upload_files_op");
|
||||||
if(uploadFilesOp!=null) {
|
changeListener(uploadFilesOp,uploadAttachHandler2);
|
||||||
uploadFilesOp.removeEventListener("change", uploadAttachHandler2, false);
|
|
||||||
uploadFilesOp.addEventListener("change", uploadAttachHandler2, false);
|
|
||||||
}
|
|
||||||
bindAttachManager();
|
bindAttachManager();
|
||||||
|
|
||||||
function bindAttachItems() {
|
function bindAttachItems() {
|
||||||
|
@ -212,73 +212,6 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
||||||
bindAttachItems();
|
bindAttachItems();
|
||||||
bindAttachManager();
|
bindAttachManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".moderate_link").unbind("click");
|
|
||||||
$(".mod_floater_submit").unbind("click");
|
|
||||||
$(".moderate_link").click(ev => {
|
|
||||||
ev.preventDefault();
|
|
||||||
$(".pre_opt").removeClass("auto_hide");
|
|
||||||
$(".moderate_link").addClass("moderate_open");
|
|
||||||
$("#topicsItemList,#forumItemList").addClass("topics_moderate");
|
|
||||||
$(".topic_row").each(function(){
|
|
||||||
$(this).click(function(){
|
|
||||||
selectedTopics.push(parseInt($(this).attr("data-tid"),10));
|
|
||||||
if(selectedTopics.length==1) {
|
|
||||||
var msg = phraseBox["topic_list"]["topic_list.what_to_do_single"];
|
|
||||||
} else {
|
|
||||||
var msg = "What do you want to do with these "+selectedTopics.length+" topics?";
|
|
||||||
}
|
|
||||||
$(".mod_floater_head span").html(msg);
|
|
||||||
$(this).addClass("topic_selected");
|
|
||||||
$(".mod_floater").removeClass("auto_hide");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let bulkActionSender = (action,selectedTopics,fragBit) => {
|
|
||||||
$.ajax({
|
|
||||||
url: "/topic/"+action+"/submit/"+fragBit+"?s="+me.User.S,
|
|
||||||
type: "POST",
|
|
||||||
data: JSON.stringify(selectedTopics),
|
|
||||||
contentType: "application/json",
|
|
||||||
error: ajaxError,
|
|
||||||
success: () => {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// TODO: Should we unbind this here to avoid binding multiple listeners to this accidentally?
|
|
||||||
$(".mod_floater_submit").click(function(ev){
|
|
||||||
ev.preventDefault();
|
|
||||||
let selectNode = this.form.querySelector(".mod_floater_options");
|
|
||||||
let optionNode = selectNode.options[selectNode.selectedIndex];
|
|
||||||
let action = optionNode.getAttribute("value");
|
|
||||||
|
|
||||||
// Handle these specially
|
|
||||||
switch(action) {
|
|
||||||
case "move":
|
|
||||||
console.log("move action");
|
|
||||||
let modTopicMover = $("#mod_topic_mover");
|
|
||||||
$("#mod_topic_mover").removeClass("auto_hide");
|
|
||||||
$("#mod_topic_mover .pane_row").click(function(){
|
|
||||||
modTopicMover.find(".pane_row").removeClass("pane_selected");
|
|
||||||
let fid = this.getAttribute("data-fid");
|
|
||||||
if(fid==null) return;
|
|
||||||
this.classList.add("pane_selected");
|
|
||||||
console.log("fid",fid);
|
|
||||||
forumToMoveTo = fid;
|
|
||||||
|
|
||||||
$("#mover_submit").unbind("click");
|
|
||||||
$("#mover_submit").click(ev => {
|
|
||||||
ev.preventDefault();
|
|
||||||
bulkActionSender("move",selectedTopics,forumToMoveTo);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bulkActionSender(action,selectedTopics,"");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function addPollInput() {
|
function addPollInput() {
|
||||||
console.log("clicked on pollinputinput");
|
console.log("clicked on pollinputinput");
|
||||||
|
@ -306,4 +239,74 @@ var imageExts = ["png","jpg","jpe","jpeg","jif","jfi","jfif","svg","bmp","gif","
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
//addInitHook("after_init_bind_page", () => {
|
||||||
|
addHook("end_bind_page", () => {
|
||||||
|
$(".moderate_link").unbind("click");
|
||||||
|
$(".mod_floater_submit").unbind("click");
|
||||||
|
$(".moderate_link").click(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
$(".pre_opt").removeClass("auto_hide");
|
||||||
|
$(".moderate_link").addClass("moderate_open");
|
||||||
|
$("#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"];
|
||||||
|
} else {
|
||||||
|
var msg = "What do you want to do with these "+selectedTopics.length+" topics?";
|
||||||
|
}
|
||||||
|
$(".mod_floater_head span").html(msg);
|
||||||
|
$(this).addClass("topic_selected");
|
||||||
|
$(".mod_floater").removeClass("auto_hide");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let bulkActionSender = (action,selectedTopics,fragBit) => {
|
||||||
|
$.ajax({
|
||||||
|
url: "/topic/"+action+"/submit/"+fragBit+"?s="+me.User.S,
|
||||||
|
type: "POST",
|
||||||
|
data: JSON.stringify(selectedTopics),
|
||||||
|
contentType: "application/json",
|
||||||
|
error: ajaxError,
|
||||||
|
success: () => {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// TODO: Should we unbind this here to avoid binding multiple listeners to this accidentally?
|
||||||
|
$(".mod_floater_submit").click(function(ev){
|
||||||
|
ev.preventDefault();
|
||||||
|
let selectNode = this.form.querySelector(".mod_floater_options");
|
||||||
|
let optionNode = selectNode.options[selectNode.selectedIndex];
|
||||||
|
let action = optionNode.getAttribute("value");
|
||||||
|
|
||||||
|
// Handle these specially
|
||||||
|
switch(action) {
|
||||||
|
case "move":
|
||||||
|
console.log("move action");
|
||||||
|
let modTopicMover = $("#mod_topic_mover");
|
||||||
|
$("#mod_topic_mover").removeClass("auto_hide");
|
||||||
|
$("#mod_topic_mover .pane_row").click(function(){
|
||||||
|
modTopicMover.find(".pane_row").removeClass("pane_selected");
|
||||||
|
let fid = this.getAttribute("data-fid");
|
||||||
|
if(fid==null) return;
|
||||||
|
this.classList.add("pane_selected");
|
||||||
|
console.log("fid",fid);
|
||||||
|
forumToMoveTo = fid;
|
||||||
|
|
||||||
|
$("#mover_submit").unbind("click");
|
||||||
|
$("#mover_submit").click(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
bulkActionSender("move",selectedTopics,forumToMoveTo);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bulkActionSender(action,selectedTopics,"");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
})()
|
})()
|
|
@ -54,8 +54,14 @@ func ViewForum(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Header, s
|
||||||
return nil
|
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)
|
//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
|
tmpl := forum.Tmpl
|
||||||
if tmpl == "" {
|
if tmpl == "" {
|
||||||
ferr = renderTemplate("forum", w, r, h, pi)
|
ferr = renderTemplate("forum", w, r, h, pi)
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"github.com/Azareal/Gosora/common/phrases"
|
"github.com/Azareal/Gosora/common/phrases"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ForumList(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header) c.RouteError {
|
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, user, h)
|
/*skip, rerr := h.Hooks.VhookSkippable("route_forum_list_start", w, r, u, h)
|
||||||
if skip || rerr != nil {
|
if skip || rerr != nil {
|
||||||
return rerr
|
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 {
|
if skip || rerr != nil {
|
||||||
return rerr
|
return rerr
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,18 @@ func ForumList(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var canSee []int
|
var canSee []int
|
||||||
if user.IsSuperAdmin {
|
if u.IsSuperAdmin {
|
||||||
canSee, err = c.Forums.GetAllVisibleIDs()
|
canSee, err = c.Forums.GetAllVisibleIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
group, err := c.Groups.Get(user.Group)
|
g, err := c.Groups.Get(u.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Group #%d doesn't exist despite being used by c.User #%d", user.Group, user.ID)
|
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, user)
|
return c.LocalError("Something weird happened", w, r, u)
|
||||||
}
|
}
|
||||||
canSee = group.CanSee
|
canSee = g.CanSee
|
||||||
}
|
}
|
||||||
|
|
||||||
var forumList []c.Forum
|
var forumList []c.Forum
|
||||||
|
|
|
@ -11,13 +11,13 @@ import (
|
||||||
p "github.com/Azareal/Gosora/common/phrases"
|
p "github.com/Azareal/Gosora/common/phrases"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Forums(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
func Forums(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||||
basePage, ferr := buildBasePage(w, r, user, "forums", "forums")
|
basePage, ferr := buildBasePage(w, r, u, "forums", "forums")
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
basePage.Header.AddScript("Sortable-1.4.0/Sortable.min.js")
|
basePage.Header.AddScript("Sortable-1.4.0/Sortable.min.js")
|
||||||
basePage.Header.AddScriptAsync("panel_forums.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})
|
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 {
|
func ForumsCreateSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
fname := r.PostFormValue("name")
|
name := r.PostFormValue("name")
|
||||||
fdesc := r.PostFormValue("desc")
|
desc := r.PostFormValue("desc")
|
||||||
fpreset := c.StripInvalidPreset(r.PostFormValue("preset"))
|
preset := c.StripInvalidPreset(r.PostFormValue("preset"))
|
||||||
factive := r.PostFormValue("active")
|
factive := r.PostFormValue("active")
|
||||||
active := (factive == "on" || factive == "1")
|
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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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
|
// TODO: Revamp this
|
||||||
func ForumsDelete(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
func ForumsDelete(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||||
basePage, ferr := buildBasePage(w, r, user, "delete_forum", "forums")
|
basePage, ferr := buildBasePage(w, r, u, "delete_forum", "forums")
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
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)
|
forum, err := c.Forums.Get(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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}
|
youSure := c.AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid), confirmMsg}
|
||||||
|
|
||||||
pi := c.PanelPage{basePage, tList, youSure}
|
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 nil
|
||||||
}
|
}
|
||||||
return renderTemplate("panel_are_you_sure", w, r, basePage.Header, &pi)
|
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 {
|
func ForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
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)
|
err = c.Forums.Delete(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
@ -139,14 +139,14 @@ func ForumsDeleteSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sf
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForumsOrderSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
func ForumsOrderSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
js := r.PostFormValue("js") == "1"
|
js := r.PostFormValue("js") == "1"
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissionsJSQ(w, r, user, js)
|
return c.NoPermissionsJSQ(w, r, u, js)
|
||||||
}
|
}
|
||||||
sitems := strings.TrimSuffix(strings.TrimPrefix(r.PostFormValue("items"), "{"), "}")
|
sitems := strings.TrimSuffix(strings.TrimPrefix(r.PostFormValue("items"), "{"), "}")
|
||||||
//fmt.Printf("sitems: %+v\n", sitems)
|
//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, ",") {
|
for index, sfid := range strings.Split(sitems, ",") {
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
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
|
updateMap[fid] = index
|
||||||
}
|
}
|
||||||
c.Forums.UpdateOrder(updateMap)
|
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 {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
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)
|
return successRedirect("/panel/forums/", w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForumsEdit(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
func ForumsEdit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||||
basePage, ferr := buildBasePage(w, r, user, "edit_forum", "forums")
|
basePage, ferr := buildBasePage(w, r, u, "edit_forum", "forums")
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
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)
|
forum, err := c.Forums.Get(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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})
|
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 {
|
func ForumsEditSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
js := r.PostFormValue("js") == "1"
|
js := r.PostFormValue("js") == "1"
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
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)
|
forum, err := c.Forums.Get(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
fname := r.PostFormValue("forum_name")
|
name := r.PostFormValue("forum_name")
|
||||||
fdesc := r.PostFormValue("forum_desc")
|
desc := r.PostFormValue("forum_desc")
|
||||||
fpreset := c.StripInvalidPreset(r.PostFormValue("forum_preset"))
|
preset := c.StripInvalidPreset(r.PostFormValue("forum_preset"))
|
||||||
factive := r.PostFormValue("forum_active")
|
factive := r.PostFormValue("forum_active")
|
||||||
|
|
||||||
active := false
|
active := false
|
||||||
|
@ -255,11 +255,11 @@ func ForumsEditSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid
|
||||||
active = true
|
active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
err = forum.Update(fname, fdesc, active, fpreset)
|
err = forum.Update(name, desc, active, preset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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)
|
return successRedirect("/panel/forums/", w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sfid string) c.RouteError {
|
func ForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sfid string) c.RouteError {
|
||||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
js := r.PostFormValue("js") == "1"
|
js := r.PostFormValue("js") == "1"
|
||||||
|
|
||||||
fid, err := strconv.Atoi(sfid)
|
fid, err := strconv.Atoi(sfid)
|
||||||
if err != nil {
|
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"))
|
gid, err := strconv.Atoi(r.PostFormValue("gid"))
|
||||||
if err != nil {
|
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)
|
forum, err := c.Forums.Get(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
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"))
|
permPreset := c.StripInvalidGroupForumPreset(r.PostFormValue("perm_preset"))
|
||||||
err = forum.SetPreset(permPreset, gid)
|
err = forum.SetPreset(permPreset, gid)
|
||||||
if err != nil {
|
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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
@ -328,23 +327,23 @@ func forumPermsExtractDash(paramList string) (fid, gid int, err error) {
|
||||||
return fid, gid, err
|
return fid, gid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForumsEditPermsAdvance(w http.ResponseWriter, r *http.Request, user *c.User, paramList string) c.RouteError {
|
func ForumsEditPermsAdvance(w http.ResponseWriter, r *http.Request, u *c.User, paramList string) c.RouteError {
|
||||||
basePage, ferr := buildBasePage(w, r, user, "edit_forum", "forums")
|
basePage, ferr := buildBasePage(w, r, u, "edit_forum", "forums")
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
fid, gid, err := forumPermsExtractDash(paramList)
|
fid, gid, err := forumPermsExtractDash(paramList)
|
||||||
if err != nil {
|
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)
|
f, err := c.Forums.Get(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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})
|
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 {
|
func ForumsEditPermsAdvanceSubmit(w http.ResponseWriter, r *http.Request, u *c.User, paramList string) c.RouteError {
|
||||||
_, ferr := c.SimplePanelUserCheck(w, r, user)
|
_, ferr := c.SimplePanelUserCheck(w, r, u)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ManageForums {
|
if !u.Perms.ManageForums {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
js := r.PostFormValue("js") == "1"
|
js := r.PostFormValue("js") == "1"
|
||||||
|
|
||||||
fid, gid, err := forumPermsExtractDash(paramList)
|
fid, gid, err := forumPermsExtractDash(paramList)
|
||||||
if err != nil {
|
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)
|
forum, err := c.Forums.Get(fid)
|
||||||
if err == sql.ErrNoRows {
|
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 {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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)
|
err = forum.SetPerms(&fp, "custom", gid)
|
||||||
if err != nil {
|
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 {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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}
|
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 {
|
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)
|
/*skip, rerr := h.Hooks.VhookSkippable("route_topic_list_start", w, r, u, h)
|
||||||
if skip || rerr != nil {
|
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 topicList []*c.TopicsRow
|
||||||
var forumList []c.Forum
|
var forumList []c.Forum
|
||||||
var pagi c.Paginator
|
var pagi c.Paginator
|
||||||
var canLock, ccanLock, canMove, ccanMove bool
|
var canDelete, ccanDelete, canLock, ccanLock, canMove, ccanMove bool
|
||||||
q := r.FormValue("q")
|
q := r.FormValue("q")
|
||||||
if q != "" && c.RepliesSearch != nil {
|
if q != "" && c.RepliesSearch != nil {
|
||||||
var canSee []int
|
var canSee []int
|
||||||
|
@ -152,34 +167,45 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
||||||
|
|
||||||
// TODO: De-dupe this logic in common/topic_list.go?
|
// TODO: De-dupe this logic in common/topic_list.go?
|
||||||
//var sb strings.Builder
|
//var sb strings.Builder
|
||||||
|
fps := make(map[int]c.QuickTools)
|
||||||
for _, t := range topicList {
|
for _, t := range topicList {
|
||||||
//c.BuildTopicURLSb(&sb, c.NameToSlug(t.Title), t.ID)
|
//c.BuildTopicURLSb(&sb, c.NameToSlug(t.Title), t.ID)
|
||||||
//t.Link = sb.String()
|
//t.Link = sb.String()
|
||||||
//sb.Reset()
|
//sb.Reset()
|
||||||
t.Link = c.BuildTopicURL(c.NameToSlug(t.Title), t.ID)
|
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.
|
// 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)
|
f := c.Forums.DirtyGet(t.ParentID)
|
||||||
t.ForumName = forum.Name
|
t.ForumName = f.Name
|
||||||
t.ForumLink = forum.Link
|
t.ForumLink = f.Link
|
||||||
|
|
||||||
fp, err := c.FPStore.Get(forum.ID, user.Group)
|
_, ok := fps[f.ID]
|
||||||
if err == c.ErrNoRows {
|
if !ok {
|
||||||
fp = c.BlankForumPerms()
|
// TODO: Abstract this?
|
||||||
} else if err != nil {
|
fp, err := c.FPStore.Get(f.ID, user.Group)
|
||||||
return c.InternalError(err, w, r)
|
if err == c.ErrNoRows {
|
||||||
}
|
fp = c.BlankForumPerms()
|
||||||
if fp.Overrides && !user.IsSuperAdmin {
|
} else if err != nil {
|
||||||
ccanLock = fp.CloseTopic
|
return c.InternalError(err, w, r)
|
||||||
ccanMove = fp.MoveTopic
|
}
|
||||||
} else {
|
if fp.Overrides && !user.IsSuperAdmin {
|
||||||
ccanLock = user.Perms.CloseTopic
|
ccanDelete = fp.DeleteTopic
|
||||||
ccanMove = user.Perms.MoveTopic
|
ccanLock = fp.CloseTopic
|
||||||
}
|
ccanMove = fp.MoveTopic
|
||||||
if ccanLock {
|
} else {
|
||||||
canLock = true
|
ccanDelete = user.Perms.DeleteTopic
|
||||||
}
|
ccanLock = user.Perms.CloseTopic
|
||||||
if ccanMove {
|
ccanMove = user.Perms.MoveTopic
|
||||||
canMove = true
|
}
|
||||||
|
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
|
// TODO: Create a specialised function with a bit less overhead for getting the last page for a post count
|
||||||
|
@ -192,7 +218,7 @@ func TopicListCommon(w http.ResponseWriter, r *http.Request, user *c.User, h *c.
|
||||||
|
|
||||||
// TODO: Reduce the amount of boilerplate here
|
// TODO: Reduce the amount of boilerplate here
|
||||||
if r.FormValue("js") == "1" {
|
if r.FormValue("js") == "1" {
|
||||||
outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON()
|
outBytes, err := wsTopicList2(topicList, user, fps, pagi.LastPage).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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
|
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")
|
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)
|
return renderTemplate("topics", w, r, h, pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pass a struct back rather than passing back so many variables
|
// TODO: Pass a struct back rather than passing back so many variables
|
||||||
|
var fps map[int]c.QuickTools
|
||||||
if user.IsSuperAdmin {
|
if user.IsSuperAdmin {
|
||||||
topicList, forumList, pagi, err = c.TopicList.GetList(page, tsorder, fids)
|
topicList, forumList, pagi, err = c.TopicList.GetList(page, tsorder, fids)
|
||||||
canLock, canMove = true, true
|
canLock, canMove = true, true
|
||||||
} else {
|
} else {
|
||||||
topicList, forumList, pagi, err = c.TopicList.GetListByGroup(group, page, tsorder, fids)
|
topicList, forumList, pagi, err = c.TopicList.GetListByGroup(group, page, tsorder, fids)
|
||||||
for _, forum := range forumList {
|
fps = make(map[int]c.QuickTools)
|
||||||
fp, err := c.FPStore.Get(forum.ID, user.Group)
|
for _, f := range forumList {
|
||||||
|
fp, err := c.FPStore.Get(f.ID, user.Group)
|
||||||
if err == c.ErrNoRows {
|
if err == c.ErrNoRows {
|
||||||
fp = c.BlankForumPerms()
|
fp = c.BlankForumPerms()
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
if fp.Overrides {
|
if fp.Overrides {
|
||||||
|
ccanDelete = fp.DeleteTopic
|
||||||
ccanLock = fp.CloseTopic
|
ccanLock = fp.CloseTopic
|
||||||
ccanMove = fp.MoveTopic
|
ccanMove = fp.MoveTopic
|
||||||
} else {
|
} else {
|
||||||
|
ccanDelete = user.Perms.DeleteTopic
|
||||||
ccanLock = user.Perms.CloseTopic
|
ccanLock = user.Perms.CloseTopic
|
||||||
ccanMove = user.Perms.MoveTopic
|
ccanMove = user.Perms.MoveTopic
|
||||||
}
|
}
|
||||||
|
if ccanDelete {
|
||||||
|
canDelete = true
|
||||||
|
}
|
||||||
if ccanLock {
|
if ccanLock {
|
||||||
canLock = true
|
canLock = true
|
||||||
}
|
}
|
||||||
if ccanMove {
|
if ccanMove {
|
||||||
canMove = true
|
canMove = true
|
||||||
}
|
}
|
||||||
|
fps[f.ID] = c.QuickTools{ccanDelete, ccanLock, ccanMove}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
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
|
// TODO: Reduce the amount of boilerplate here
|
||||||
if r.FormValue("js") == "1" {
|
if r.FormValue("js") == "1" {
|
||||||
outBytes, err := wsTopicList(topicList, pagi.LastPage).MarshalJSON()
|
outBytes, err := wsTopicList2(topicList, user, fps, pagi.LastPage).MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
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
|
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" {
|
if r.FormValue("i") == "1" {
|
||||||
return renderTemplate("topics_mini", w, r, h, pi)
|
return renderTemplate("topics_mini", w, r, h, pi)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Generating the JSON handlers
|
||||||
|
easyjson -pkg common
|
||||||
|
|
||||||
echo Building the hook generator
|
echo Building the hook generator
|
||||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Generating the JSON handlers
|
|
||||||
easyjson -pkg common
|
|
||||||
|
|
||||||
echo Building the query generator
|
echo Building the query generator
|
||||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Generating the JSON handlers
|
||||||
|
easyjson -pkg common
|
||||||
|
|
||||||
echo Building the hook generator
|
echo Building the hook generator
|
||||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Generating the JSON handlers
|
|
||||||
easyjson -pkg common
|
|
||||||
|
|
||||||
echo Building the query generator
|
echo Building the query generator
|
||||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Generating the JSON handlers
|
||||||
|
easyjson -pkg common
|
||||||
|
|
||||||
echo Building the hook generator
|
echo Building the hook generator
|
||||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Generating the JSON handlers
|
|
||||||
easyjson -pkg common
|
|
||||||
|
|
||||||
echo Building the query generator
|
echo Building the query generator
|
||||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
|
|
@ -41,6 +41,9 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
|
echo Generating the JSON handlers
|
||||||
|
easyjson -pkg common
|
||||||
|
|
||||||
echo Building the hook generator
|
echo Building the hook generator
|
||||||
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
go build -tags hookgen -ldflags="-s -w" "./cmd/hook_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
@ -54,9 +57,6 @@ if %errorlevel% neq 0 (
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Generating the JSON handlers
|
|
||||||
easyjson -pkg common
|
|
||||||
|
|
||||||
echo Building the query generator
|
echo Building the query generator
|
||||||
go build -ldflags="-s -w" "./cmd/query_gen"
|
go build -ldflags="-s -w" "./cmd/query_gen"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
<div id="forum_topic_list"class="rowblock topic_list single_forum"aria-label="{{lang "forum_list_aria"}}">
|
<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">
|
<div class="rowitem topic_left passive datarow">
|
||||||
<span class="selector"></span>
|
<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>
|
<a href="{{.Creator.Link}}"><img src="{{.Creator.MicroAvatar}}"height=64 alt="Avatar"title="{{.Creator.Name}}'s Avatar"aria-hidden="true"></a>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><h1>{{lang "panel_pages_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "panel_pages_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_pages" class="colstack_item rowlist">
|
<div id="panel_pages"class="colstack_item rowlist">
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
<div class="rowitem panel_compactrow">
|
<div class="rowitem panel_compactrow">
|
||||||
<a href="/panel/pages/edit/{{.ID}}" class="panel_upshift">{{.Title}}</a> <a href="/pages/{{.Name}}">[{{.Name}}]</a>
|
<a href="/panel/pages/edit/{{.ID}}"class="panel_upshift">{{.Title}}</a> <a href="/pages/{{.Name}}">[{{.Name}}]</a>
|
||||||
<span class="panel_buttons">
|
<span class="panel_buttons">
|
||||||
<a href="/panel/pages/edit/{{.ID}}" class="panel_tag panel_right_button edit_button" aria-label="{{lang "panel_pages_edit_button_aria"}}"></a>
|
<a href="/panel/pages/edit/{{.ID}}"class="panel_tag panel_right_button edit_button"aria-label="{{lang "panel_pages_edit_button_aria"}}"></a>
|
||||||
<a href="/panel/pages/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="panel_tag panel_right_button delete_button" aria-label="{{lang "panel_pages_delete_button_aria"}}"></a>
|
<a href="/panel/pages/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}"class="panel_tag panel_right_button delete_button"aria-label="{{lang "panel_pages_delete_button_aria"}}"></a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -21,22 +21,22 @@
|
||||||
<div class="rowitem"><h1>{{lang "panel_pages_create_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "panel_pages_create_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item the_form">
|
<div class="colstack_item the_form">
|
||||||
<form action="/panel/pages/create/submit/?s={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/pages/create/submit/?s={{.CurrentUser.Session}}"method="post">
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_pages_create_name"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_pages_create_name"}}</a></div>
|
||||||
<div class="formitem"><input name="name" type="text" placeholder="{{lang "panel_pages_create_name_placeholder"}}"></div>
|
<div class="formitem"><input name="name"type="text"placeholder="{{lang "panel_pages_create_name_placeholder"}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_pages_create_title"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_pages_create_title"}}</a></div>
|
||||||
<div class="formitem"><input name="title" type="text" placeholder="{{lang "panel_pages_create_title_placeholder"}}"></div>
|
<div class="formitem"><input name="title"type="text"placeholder="{{lang "panel_pages_create_title_placeholder"}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<textarea name="body" placeholder="{{lang "panel_pages_create_body_placeholder"}}"></textarea>
|
<textarea name="body"placeholder="{{lang "panel_pages_create_body_placeholder"}}"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem"><button name="panel-button" class="formbutton form_middle_button">{{lang "panel_pages_create_button"}}</button></div>
|
<div class="formitem"><button name="panel-button"class="formbutton form_middle_button">{{lang "panel_pages_create_button"}}</button></div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
|
@ -3,20 +3,20 @@
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><h1>{{lang "panel_themes_menus_edit_head"}}</h1></div>
|
<div class="rowitem"><h1>{{lang "panel_themes_menus_edit_head"}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<form action="/panel/themes/menus/item/edit/submit/{{.Item.ID}}?s={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/themes/menus/item/edit/submit/{{.Item.ID}}?s={{.CurrentUser.Session}}"method="post">
|
||||||
<div id="panel_themes_menu_item_edit" class="colstack_item the_form">
|
<div id="panel_themes_menu_item_edit"class="colstack_item the_form">
|
||||||
{{/** TODO: Let an admin move a menu item from one menu to another? **/}}
|
{{/** TODO: Let an admin move a menu item from one menu to another? **/}}
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_name"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_name"}}</a></div>
|
||||||
<div class="formitem"><input name="item-name" type="text" value="{{.Item.Name}}"></div>
|
<div class="formitem"><input name="item-name"type="text"value="{{.Item.Name}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_htmlid"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_htmlid"}}</a></div>
|
||||||
<div class="formitem"><input name="item-htmlid" type="text" value="{{.Item.HTMLID}}"></div>
|
<div class="formitem"><input name="item-htmlid"type="text"value="{{.Item.HTMLID}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_cssclass"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_cssclass"}}</a></div>
|
||||||
<div class="formitem"><input name="item-cssclass" type="text" value="{{.Item.CSSClass}}"></div>
|
<div class="formitem"><input name="item-cssclass"type="text"value="{{.Item.CSSClass}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_position"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_position"}}</a></div>
|
||||||
|
@ -29,19 +29,19 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_path"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_path"}}</a></div>
|
||||||
<div class="formitem"><input name="item-path" type="text" value="{{.Item.Path}}"></div>
|
<div class="formitem"><input name="item-path"type="text"value="{{.Item.Path}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_aria"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_aria"}}</a></div>
|
||||||
<div class="formitem"><input name="item-aria" type="text" value="{{.Item.Aria}}"></div>
|
<div class="formitem"><input name="item-aria"type="text"value="{{.Item.Aria}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_tooltip"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_tooltip"}}</a></div>
|
||||||
<div class="formitem"><input name="item-tooltip" type="text" value="{{.Item.Tooltip}}"></div>
|
<div class="formitem"><input name="item-tooltip"type="text"value="{{.Item.Tooltip}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_tmplname"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_tmplname"}}</a></div>
|
||||||
<div class="formitem"><input name="item-tmplname" type="text" value="{{.Item.TmplName}}"></div>
|
<div class="formitem"><input name="item-tmplname"type="text"value="{{.Item.TmplName}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_permissions"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_permissions"}}</a></div>
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<button name="panel-button" class="formbutton">{{lang "panel_themes_menus_edit_update_button"}}</button>
|
<button name="panel-button"class="formbutton">{{lang "panel_themes_menus_edit_update_button"}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if .CurrentUser.Loggedin}}
|
{{if .CurrentUser.Loggedin}}
|
||||||
{{template "topics_mod_floater.html" .}}
|
{{template "topics_mod_floater.html" . }}
|
||||||
|
|
||||||
{{if .ForumList}}
|
{{if .ForumList}}
|
||||||
{{/** TODO: Have a seperate forum list for moving topics? Maybe an AJAX forum search compatible with plugin_guilds? **/}}
|
{{/** TODO: Have a seperate forum list for moving topics? Maybe an AJAX forum search compatible with plugin_guilds? **/}}
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock topic_create_form quick_create_form auto_hide"aria-label="{{lang "quick_topic.aria"}}">
|
<div class="rowblock topic_create_form quick_create_form auto_hide"aria-label="{{lang "quick_topic.aria"}}">
|
||||||
<form name="topic_create_form_form"id="quick_post_form"enctype="multipart/form-data"action="/topic/create/submit/?s={{.CurrentUser.Session}}" method="post"></form>
|
<form name="topic_create_form_form"id="quick_post_form"enctype="multipart/form-data"action="/topic/create/submit/?s={{.CurrentUser.Session}}"method="post"></form>
|
||||||
<img class="little_row_avatar"src="{{.CurrentUser.MicroAvatar}}"height=64 alt="{{lang "quick_topic.avatar_alt"}}"title="{{lang "quick_topic.avatar_tooltip"}}">
|
<img class="little_row_avatar"src="{{.CurrentUser.MicroAvatar}}"height=64 alt="{{lang "quick_topic.avatar_alt"}}"title="{{lang "quick_topic.avatar_tooltip"}}">
|
||||||
<div class="main_form">
|
<div class="main_form">
|
||||||
<div class="topic_meta">
|
<div class="topic_meta">
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="mod_floater_body">
|
<div class="mod_floater_body">
|
||||||
<select class="mod_floater_options">
|
<select class="mod_floater_options">
|
||||||
<option value="delete">{{lang "topic_list.moderate_delete"}}</option>
|
<option class="val_delete" value="delete">{{lang "topic_list.moderate_delete"}}</option>
|
||||||
{{if .CanLock}}<option value="lock">{{lang "topic_list.moderate_lock"}}</option>{{end}}
|
<option class="val_lock{{if not .CanLock}} auto_hide{{end}}" value="lock">{{lang "topic_list.moderate_lock"}}</option>
|
||||||
{{if .CanMove}}<option value="move">{{lang "topic_list.moderate_move"}}</option>{{end}}
|
<option class="val_move{{if not .CanMove}} auto_hide{{end}}" value="move">{{lang "topic_list.moderate_move"}}</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="mod_floater_submit">{{lang "topic_list.moderate_run"}}</button>
|
<button class="mod_floater_submit">{{lang "topic_list.moderate_run"}}</button>
|
||||||
</div>
|
</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">
|
<div class="rowitem topic_left passive datarow">
|
||||||
<span class="selector"></span>
|
<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>
|
<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 {
|
.topic_sticky .topic_left, .topic_sticky .topic_right {
|
||||||
border-bottom: 2px solid hsl(51, 60%, 70%);
|
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%);
|
background-color: hsl(81, 60%, 97%);
|
||||||
}
|
}
|
||||||
.topic_selected .topic_left, .topic_selected .topic_right {
|
.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">
|
<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>
|
<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">
|
<span class="topic_inner_left">
|
||||||
|
|
|
@ -228,7 +228,10 @@ li a {
|
||||||
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem, .sidebar .search {
|
.sidebar .rowblock:not(.topic_list):not(.rowhead):not(.opthead) .rowitem, .sidebar .search {
|
||||||
margin-left: 12px;
|
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);
|
background-color: rgb(78, 78, 98);
|
||||||
}
|
}
|
||||||
.widget_search:first-child {
|
.widget_search:first-child {
|
||||||
|
@ -552,7 +555,7 @@ h2 {
|
||||||
.topic_closed {
|
.topic_closed {
|
||||||
background-color: #4b4b4b;
|
background-color: #4b4b4b;
|
||||||
}
|
}
|
||||||
.topic_selected {
|
.topic_row.topic_selected {
|
||||||
background-color: rgb(68, 68, 88);
|
background-color: rgb(68, 68, 88);
|
||||||
}
|
}
|
||||||
.new_item .topic_left {
|
.new_item .topic_left {
|
||||||
|
|
|
@ -855,12 +855,18 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
|
||||||
.topic_list .topic_row {
|
.topic_list .topic_row {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.topics_moderate .topic_row:hover .rowitem {
|
.topics_moderate .topic_row:not(.can_mod) .rowitem {
|
||||||
background-color: hsla(0, 0%, 27%, 1);
|
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);
|
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 */
|
/* Temporary hack, so that I don't break the topic lists of the other themes */
|
||||||
.topic_list .topic_inner_right {
|
.topic_list .topic_inner_right {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
Loading…
Reference in New Issue