diff --git a/cmd/query_gen/tables.go b/cmd/query_gen/tables.go
index f2719494..0064c832 100644
--- a/cmd/query_gen/tables.go
+++ b/cmd/query_gen/tables.go
@@ -277,6 +277,7 @@ func createTables(adapter qgen.Adapter) error {
tblColumn{"originTable", "varchar", 200, false, false, "replies"},
tblColumn{"uploadedBy", "int", 0, false, false, ""}, // TODO; Make this a foreign key
tblColumn{"path", "varchar", 200, false, false, ""},
+ //tblColumn{"extra", "varchar", 200, false, false, ""},
},
[]tblKey{
tblKey{"attachID", "primary"},
diff --git a/common/attachments.go b/common/attachments.go
index a8ad1f51..c3e36bdf 100644
--- a/common/attachments.go
+++ b/common/attachments.go
@@ -81,7 +81,7 @@ func (store *DefaultAttachmentStore) BulkMiniGetList(originTable string, ids []i
}
if len(ids) == 1 {
res, err := store.MiniGetList(originTable, ids[0])
- return map[int][]*MiniAttachment{0: res}, err
+ return map[int][]*MiniAttachment{ids[0]: res}, err
}
amap = make(map[int][]*MiniAttachment)
diff --git a/common/extend.go b/common/extend.go
index fe7d49f7..ce0b0d35 100644
--- a/common/extend.go
+++ b/common/extend.go
@@ -88,7 +88,8 @@ var hookTable = &HookTable{
"action_end_edit_reply": nil,
"action_end_delete_reply": nil,
- "router_pre_route": nil,
+ "router_after_filters": nil,
+ "router_pre_route": nil,
},
map[string][]func(string) string{
"preparse_preassign": nil,
diff --git a/common/parser.go b/common/parser.go
index ad66a8d1..e2ee0776 100644
--- a/common/parser.go
+++ b/common/parser.go
@@ -9,13 +9,14 @@ import (
"unicode/utf8"
)
+// TODO: Somehow localise these?
var SpaceGap = []byte(" ")
var httpProtBytes = []byte("http://")
-var InvalidURL = []byte("[Invalid URL] ")
-var InvalidTopic = []byte("[Invalid Topic] ")
-var InvalidProfile = []byte("[Invalid Profile] ")
-var InvalidForum = []byte("[Invalid Forum] ")
-var unknownMedia = []byte("[Unknown Media] ")
+var InvalidURL = []byte("[Invalid URL] ")
+var InvalidTopic = []byte("[Invalid Topic] ")
+var InvalidProfile = []byte("[Invalid Profile] ")
+var InvalidForum = []byte("[Invalid Forum] ")
+var unknownMedia = []byte("[Unknown Media] ")
var URLOpen = []byte("")
var bytesSinglequote = []byte("'")
diff --git a/gen_router.go b/gen_router.go
index 86f366ca..98a20715 100644
--- a/gen_router.go
+++ b/gen_router.go
@@ -792,11 +792,17 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
}
+ // TODO: Use the same hook table as downstream
+ hTbl := common.GetHookTable()
+ skip, ferr := hTbl.VhookSkippable("router_after_filters", w, req, prefix, extraData)
+ if skip || ferr != nil {
+ return
+ }
+
if prefix != "/ws" {
h := w.Header()
h.Set("X-Frame-Options", "deny")
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
- // TODO: Set the content policy header
h.Set("X-Content-Type-Options", "nosniff")
}
@@ -994,9 +1000,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w = common.GzipResponseWriter{Writer: gz, ResponseWriter: w}
}
- // TODO: Use the same hook table as downstream
- hTbl := common.GetHookTable()
- skip, ferr := hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
+ skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
if skip || ferr != nil {
r.handleError(ferr,w,req,user)
}
diff --git a/langs/english.json b/langs/english.json
index 03c184d6..04a870de 100644
--- a/langs/english.json
+++ b/langs/english.json
@@ -597,6 +597,7 @@
"topic.poll_vote":"Vote",
"topic.poll_results":"Results",
"topic.poll_cancel":"Cancel",
+ "topic.poll_no_results":"No one has voted yet.",
"topic.post_controls_aria":"Controls and Author Information",
"topic.unlike_tooltip":"Unlike",
"topic.unlike_aria":"Unlike this topic",
diff --git a/parser_test.go b/parser_test.go
index b79fe7a6..6edcf1b9 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -143,11 +143,13 @@ func TestParser(t *testing.T) {
msgList.Add("//"+common.Site.URL+"\n//"+common.Site.URL, " //"+common.Site.URL+" //"+common.Site.URL+" ")
msgList.Add("#tid-1", "#tid-1 ")
+ msgList.Add("#tid-0", "[Invalid Topic] ")
msgList.Add("https://"+url+"/#tid-1", "https://"+url+"/#tid-1 ")
msgList.Add("#fid-1", "#fid-1 ")
+ msgList.Add("#fid-0", "[Invalid Forum] ")
msgList.Add("@1", "@Admin ")
- msgList.Add("@0", "[Invalid Profile] ")
- msgList.Add("@-1", "[Invalid Profile] 1")
+ msgList.Add("@0", "[Invalid Profile] ")
+ msgList.Add("@-1", "[Invalid Profile] 1")
for _, item := range msgList.Items {
res := common.ParseMessage(item.Msg, 1, "forums")
diff --git a/plugin_bbcode.go b/plugin_bbcode.go
index 36a698a1..db2dde5c 100644
--- a/plugin_bbcode.go
+++ b/plugin_bbcode.go
@@ -32,9 +32,9 @@ func init() {
func initBbcode(plugin *common.Plugin) error {
plugin.AddHook("parse_assign", bbcodeFullParse)
- bbcodeInvalidNumber = []byte("[Invalid Number] ")
- bbcodeNoNegative = []byte("[No Negative Numbers] ")
- bbcodeMissingTag = []byte("[Missing Tag] ")
+ bbcodeInvalidNumber = []byte("[Invalid Number] ")
+ bbcodeNoNegative = []byte("[No Negative Numbers] ")
+ bbcodeMissingTag = []byte("[Missing Tag] ")
bbcodeBold = regexp.MustCompile(`(?s)\[b\](.*)\[/b\]`)
bbcodeItalic = regexp.MustCompile(`(?s)\[i\](.*)\[/i\]`)
diff --git a/plugin_markdown.go b/plugin_markdown.go
index 9f069c8f..fe4c1d84 100644
--- a/plugin_markdown.go
+++ b/plugin_markdown.go
@@ -29,7 +29,7 @@ func init() {
func initMarkdown(plugin *common.Plugin) error {
plugin.AddHook("parse_assign", markdownParse)
- markdownUnclosedElement = []byte("[Unclosed Element] ")
+ markdownUnclosedElement = []byte("[Unclosed Element] ")
markdownBoldTagOpen = []byte("")
markdownBoldTagClose = []byte(" ")
@@ -63,7 +63,7 @@ func markdownParse(msg string) string {
// Under Construction!
func _markdownParse(msg string, n int) string {
if n > markdownMaxDepth {
- return "[Markdown Error: Overflowed the max depth of 20] "
+ return "[Markdown Error: Overflowed the max depth of 20] "
}
var outbytes []byte
diff --git a/plugin_test.go b/plugin_test.go
index 59f51e98..bb8cdf0f 100644
--- a/plugin_test.go
+++ b/plugin_test.go
@@ -87,7 +87,7 @@ func TestBBCodeRender(t *testing.T) {
var expects string
msg = "[rand][/rand]"
- expects = "[Invalid Number] [rand][/rand]"
+ expects = "[Invalid Number] [rand][/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -96,7 +96,7 @@ func TestBBCodeRender(t *testing.T) {
}
msg = "[rand]-1[/rand]"
- expects = "[No Negative Numbers] [rand]-1[/rand]"
+ expects = "[No Negative Numbers] [rand]-1[/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -105,7 +105,7 @@ func TestBBCodeRender(t *testing.T) {
}
msg = "[rand]-01[/rand]"
- expects = "[No Negative Numbers] [rand]-01[/rand]"
+ expects = "[No Negative Numbers] [rand]-01[/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -114,7 +114,7 @@ func TestBBCodeRender(t *testing.T) {
}
msg = "[rand]NaN[/rand]"
- expects = "[Invalid Number] [rand]NaN[/rand]"
+ expects = "[Invalid Number] [rand]NaN[/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -123,7 +123,7 @@ func TestBBCodeRender(t *testing.T) {
}
msg = "[rand]Inf[/rand]"
- expects = "[Invalid Number] [rand]Inf[/rand]"
+ expects = "[Invalid Number] [rand]Inf[/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -132,7 +132,7 @@ func TestBBCodeRender(t *testing.T) {
}
msg = "[rand]+[/rand]"
- expects = "[Invalid Number] [rand]+[/rand]"
+ expects = "[Invalid Number] [rand]+[/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -141,7 +141,7 @@ func TestBBCodeRender(t *testing.T) {
}
msg = "[rand]1+1[/rand]"
- expects = "[Invalid Number] [rand]1+1[/rand]"
+ expects = "[Invalid Number] [rand]1+1[/rand]"
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
if res != expects {
@@ -191,7 +191,7 @@ func TestBBCodeRender(t *testing.T) {
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
_, err = strconv.Atoi(res)
- if err != nil && res != "[Invalid Number] [rand]18446744073709551615[/rand]" {
+ if err != nil && res != "[Invalid Number] [rand]18446744073709551615[/rand]" {
t.Error("Bad output:", "'"+res+"'")
t.Error("Expected a number between 0 and 18446744073709551615")
}
@@ -199,7 +199,7 @@ func TestBBCodeRender(t *testing.T) {
t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg)
_, err = strconv.Atoi(res)
- if err != nil && res != "[Invalid Number] [rand]170141183460469231731687303715884105727[/rand]" {
+ if err != nil && res != "[Invalid Number] [rand]170141183460469231731687303715884105727[/rand]" {
t.Error("Bad output:", "'"+res+"'")
t.Error("Expected a number between 0 and 170141183460469231731687303715884105727")
}
diff --git a/public/global.js b/public/global.js
index c33a5da7..32be662c 100644
--- a/public/global.js
+++ b/public/global.js
@@ -1170,13 +1170,24 @@ function mainInit(){
//id="poll_results_{{.Poll.ID}}" class="poll_results auto_hide"
$(".poll_results_button").click(function(){
let pollID = $(this).attr("data-poll-id");
- $("#poll_results_" + pollID + " .user_content").html("
");
$("#poll_results_" + pollID).removeClass("auto_hide");
fetch("/poll/results/" + pollID, {
credentials: 'same-origin'
}).then((response) => response.text()).catch((error) => console.error("Error:",error)).then((rawData) => {
// TODO: Make sure the received data is actually a list of integers
let data = JSON.parse(rawData);
+
+ let allZero = true;
+ for(let i = 0; i < data.length; i++) {
+ if(data[i] != "0") allZero = false;
+ }
+ if(allZero) {
+ $("#poll_results_" + pollID + " .poll_no_results").removeClass("auto_hide");
+ console.log("all zero")
+ return;
+ }
+
+ $("#poll_results_" + pollID + " .user_content").html("
");
console.log("rawData: ", rawData);
console.log("series: ", data);
Chartist.Pie('#poll_results_chart_' + pollID, {
diff --git a/router_gen/main.go b/router_gen/main.go
index 52ba0001..9d76c959 100644
--- a/router_gen/main.go
+++ b/router_gen/main.go
@@ -571,11 +571,17 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
}
+ // TODO: Use the same hook table as downstream
+ hTbl := common.GetHookTable()
+ skip, ferr := hTbl.VhookSkippable("router_after_filters", w, req, prefix, extraData)
+ if skip || ferr != nil {
+ return
+ }
+
if prefix != "/ws" {
h := w.Header()
h.Set("X-Frame-Options", "deny")
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
- // TODO: Set the content policy header
h.Set("X-Content-Type-Options", "nosniff")
}
@@ -773,9 +779,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w = common.GzipResponseWriter{Writer: gz, ResponseWriter: w}
}
- // TODO: Use the same hook table as downstream
- hTbl := common.GetHookTable()
- skip, ferr := hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
+ skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
if skip || ferr != nil {
r.handleError(ferr,w,req,user)
}
diff --git a/templates/topic.html b/templates/topic.html
index e92361c0..d7d470c5 100644
--- a/templates/topic.html
+++ b/templates/topic.html
@@ -1,6 +1,5 @@
{{template "header.html" . }}
-
{{if gt .Page 1}}
{{end}}
@@ -9,9 +8,9 @@
{{lang "paginator.greater_than"}}
{{end}}
-
+
-
+
{{if .Poll.ID}}
-
-
-
- {{range .Poll.QuickOptions}}
-
- {{end}}
-
-
-
-
-
+{{template "topic_poll.html" . }}
{{end}}
@@ -127,4 +105,4 @@
-{{template "footer.html" . }}
+{{template "footer.html" . }}
\ No newline at end of file
diff --git a/templates/topic_alt.html b/templates/topic_alt.html
index 79e6dfa0..cc613434 100644
--- a/templates/topic_alt.html
+++ b/templates/topic_alt.html
@@ -6,30 +6,29 @@
{{if ne .LastPage .Page}}
{{end}}
+
+
-
-
-
+
+
{{.Topic.Title}}
+
-
+
{{.Forum.Name}}
+ {{/** TODO: Does this need to be guarded by a permission? It's only visible in edit mode anyway, which can't be triggered, if they don't have the permission **/}}
+ {{if .CurrentUser.Loggedin}}
+ {{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
+ {{if .CurrentUser.Perms.EditTopic}}
+
+
+
{{lang "topic.update_button"}}
+ {{end}}
+ {{end}}
+ {{end}}
+
{{.Topic.ViewCount}}
+ {{/** TODO: Inline this CSS **/}}
+ {{if .Topic.IsClosed}}
🔒︎ {{end}}
+
@@ -56,7 +55,9 @@
-
+
+
{{lang "topic.poll_no_results"}}
+
{{end}}
diff --git a/templates/topic_alt_posts.html b/templates/topic_alt_posts.html
index c805c7dd..b43a088a 100644
--- a/templates/topic_alt_posts.html
+++ b/templates/topic_alt_posts.html
@@ -11,20 +11,20 @@
{{if $.CurrentUser.Perms.EditReply}}
{{if .Attachments}}
- {{range .Attachments}}
-
- {{if .Image}}
{{end}}
-
{{.Path}}
-
{{lang "topic.select_button_text"}}
-
{{lang "topic.copy_button_text"}}
-
- {{end}}
-
- {{if $.CurrentUser.Perms.UploadFiles}}
-
- {{lang "topic.upload_button_text"}} {{end}}
- {{lang "topic.delete_button_text"}}
-
+ {{range .Attachments}}
+
+ {{if .Image}}
{{end}}
+
{{.Path}}
+
{{lang "topic.select_button_text"}}
+
{{lang "topic.copy_button_text"}}
+
+ {{end}}
+
+ {{if $.CurrentUser.Perms.UploadFiles}}
+
+ {{lang "topic.upload_button_text"}} {{end}}
+ {{lang "topic.delete_button_text"}}
+
{{end}}
{{end}}{{end}}
diff --git a/templates/topic_poll.html b/templates/topic_poll.html
new file mode 100644
index 00000000..2581801f
--- /dev/null
+++ b/templates/topic_poll.html
@@ -0,0 +1,25 @@
+
+
+
+ {{range .Poll.QuickOptions}}
+
+ {{end}}
+
+
+
+
+
{{lang "topic.poll_no_results"}}
+
+
+
+
\ No newline at end of file
diff --git a/themes/cosora/public/main.css b/themes/cosora/public/main.css
index 0073b578..209e3d2e 100644
--- a/themes/cosora/public/main.css
+++ b/themes/cosora/public/main.css
@@ -521,10 +521,11 @@ input[type=checkbox] + label {
background-color: var(--element-background-color);
}
input[type=checkbox]:checked + label .sel {
- display: inline-block;
+ display: block;
width: 5px;
height: 5px;
background: var(--element-border-color);
+ margin-top: -2px;
}
.poll_content_row {
padding-left: 20px;
@@ -544,7 +545,7 @@ input[type=checkbox]:checked + label .sel {
.show_on_block_edit:not(.edit_opened),
.hide_on_block_edit.edit_opened,
.link_select:not(.link_opened) {
- display: none;
+ display: none !important;
}
input[type=checkbox] + label.poll_option_label {
@@ -552,20 +553,22 @@ input[type=checkbox] + label.poll_option_label {
height: 18px;
}
input[type=checkbox]:checked + label.poll_option_label .sel {
- display: inline-block;
+ display: block;
width: 10px;
height: 10px;
margin-left: 3px;
+ margin-top: 3px;
background: var(--element-border-color);
}
-/*.poll_option {
- margin-bottom: 3px;
-}*/
+.poll_option {
+ padding-bottom: 5px;
+ display: flex;
+}
.poll_option_text {
- display: inline-block;
- margin-left: 3px;
+ display: block;
+ margin-left: 8px;
+ margin-top: 1px;
font-size: 15px;
- /*font-weight: bold;*/
position: relative;
top: -1px;
color: var(--light-text-color);
@@ -587,6 +590,9 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
margin-left: 16px;
margin-top: 4px;
}
+.poll_results {
+ margin-left: 14px;
+}
.formbutton {
margin-top: 12px;
@@ -1078,6 +1084,9 @@ blockquote:first-child {
.user_content strong h2, .user_content strong h3, .user_content strong h4 {
font-weight: bold;
}
+red {
+ color: red;
+}
.button_container {
margin-top: auto;
display: flex;
diff --git a/themes/nox/public/main.css b/themes/nox/public/main.css
index a30f4fb1..7883a71d 100644
--- a/themes/nox/public/main.css
+++ b/themes/nox/public/main.css
@@ -868,6 +868,9 @@ blockquote:first-child {
width: 100% !important;
padding: 16px;
}
+red {
+ color: red;
+}
.user_content.in_edit a {
display: flex;
background-color: #444444;
@@ -942,6 +945,9 @@ input[type=checkbox]:checked + label .sel {
.poll_buttons button {
margin-right: 8px;
}
+.poll_results {
+ margin-left: 12px;
+}
.ip_item {
display: none;
diff --git a/themes/shadow/public/main.css b/themes/shadow/public/main.css
index ca497f5d..cbd921b8 100644
--- a/themes/shadow/public/main.css
+++ b/themes/shadow/public/main.css
@@ -280,6 +280,9 @@ h1, h2, h3, h4, h5 {
.user_content strong h2, .user_content strong h3, .user_content strong h4 {
font-weight: bold;
}
+red {
+ color: red;
+}
.controls {
width: 100%;
@@ -682,6 +685,9 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
padding-bottom: 6px;
font-size: 13px;
}
+.poll_buttons > *:not(:first-child) {
+ margin-left: 5px;
+}
.poll_results {
margin-left: auto;
max-height: 120px;
diff --git a/themes/tempra_simple/public/main.css b/themes/tempra_simple/public/main.css
index 41b895f8..6d1b236c 100644
--- a/themes/tempra_simple/public/main.css
+++ b/themes/tempra_simple/public/main.css
@@ -689,6 +689,9 @@ button.username {
.user_content strong h2, .user_content strong h3, .user_content strong h4 {
font-weight: bold;
}
+red {
+ color: red;
+}
.user_tag {
float: right;
@@ -859,6 +862,9 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
padding-bottom: 3px;
border: 1px solid hsl(0, 0%, 70%);
}
+.poll_buttons > *:not(:first-child) {
+ margin-left: 5px;
+}
.poll_results {
margin-left: auto;
}