Live Topic List should work properly now with replies too, not just new topics.
Tweaked the visuals for the live topic list on Cosora. More to come with this. Nox Theme is now present on the theme selector, although it's still under construction. Improved SEO for social media. Added the topic_list tmpl phrase prefix. Added the topic_list.changed_topics phrase. Added a few more PreparseMessage tests. Session cookies should now be deleted after you logout, not just blanked.
This commit is contained in:
parent
5d810c1e3b
commit
bf40d61474
|
@ -182,13 +182,17 @@ func setCookie(w http.ResponseWriter, cookie *http.Cookie, sameSite string) {
|
|||
}
|
||||
}
|
||||
|
||||
func deleteCookie(w http.ResponseWriter, cookie *http.Cookie) {
|
||||
cookie.MaxAge = -1
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
|
||||
// Logout logs you out of the computer you requested the logout for, but not the other computers you're logged in with
|
||||
func (auth *DefaultAuth) Logout(w http.ResponseWriter, _ int) {
|
||||
cookie := http.Cookie{Name: "uid", Value: "", Path: "/", MaxAge: int(Year)}
|
||||
setCookie(w, &cookie, "lax")
|
||||
http.SetCookie(w, &cookie)
|
||||
cookie = http.Cookie{Name: "session", Value: "", Path: "/", MaxAge: int(Year)}
|
||||
setCookie(w, &cookie, "lax")
|
||||
cookie := http.Cookie{Name: "uid", Value: "", Path: "/"}
|
||||
deleteCookie(w, &cookie)
|
||||
cookie = http.Cookie{Name: "session", Value: "", Path: "/"}
|
||||
deleteCookie(w, &cookie)
|
||||
}
|
||||
|
||||
// TODO: Set the cookie domain
|
||||
|
|
|
@ -93,11 +93,13 @@ func (hub *WsHubImpl) Tick() error {
|
|||
|
||||
//fmt.Println("checking for changes")
|
||||
// TODO: Optimise this by only sniffing the top non-sticky
|
||||
// TODO: Optimise this by getting back an unsorted list so we don't have to hop around the stickies
|
||||
// TODO: Add support for new stickies / replies to them
|
||||
if len(tList) == len(hub.lastTopicList) {
|
||||
var hasItem = false
|
||||
for j, tItem := range tList {
|
||||
if !tItem.Sticky {
|
||||
if tItem.ID != hub.lastTopicList[j].ID {
|
||||
if tItem.ID != hub.lastTopicList[j].ID || !tItem.LastReplyAt.Equal(hub.lastTopicList[j].LastReplyAt) {
|
||||
hasItem = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -424,17 +424,18 @@
|
|||
"quick_topic.add_file_button":"Add File",
|
||||
"quick_topic.cancel_button":"Cancel",
|
||||
|
||||
"topic_list_create_topic_tooltip":"Create Topic",
|
||||
"topic_list_create_topic_aria":"Create a topic",
|
||||
"topic_list_moderate_tooltip":"Moderate",
|
||||
"topic_list_moderate_aria":"Moderate Posts",
|
||||
"topic_list_what_to_do":"What do you want to do with these 18 topics?",
|
||||
"topic_list_moderate_delete":"Delete them",
|
||||
"topic_list_moderate_lock":"Lock them",
|
||||
"topic_list_moderate_move":"Move them",
|
||||
"topic_list_moderate_run":"Run",
|
||||
"topic_list_move_head":"Move these topics to?",
|
||||
"topic_list_move_button":"Move Topics",
|
||||
"topic_list.create_topic_tooltip":"Create Topic",
|
||||
"topic_list.create_topic_aria":"Create a topic",
|
||||
"topic_list.moderate_tooltip":"Moderate",
|
||||
"topic_list.moderate_aria":"Moderate Posts",
|
||||
"topic_list.what_to_do":"What do you want to do with these 18 topics?",
|
||||
"topic_list.moderate_delete":"Delete them",
|
||||
"topic_list.moderate_lock":"Lock them",
|
||||
"topic_list.moderate_move":"Move them",
|
||||
"topic_list.moderate_run":"Run",
|
||||
"topic_list.move_head":"Move these topics to?",
|
||||
"topic_list.move_button":"Move Topics",
|
||||
"topic_list.changed_topics":"Click to see %d new or changed topics",
|
||||
"status.closed_tooltip":"Status: Closed",
|
||||
"status.pinned_tooltip":"Status: Pinned",
|
||||
|
||||
|
|
|
@ -989,6 +989,11 @@ func TestPreparser(t *testing.T) {
|
|||
msgList = addMETri(msgList, "</p>", "")
|
||||
msgList = addMETri(msgList, "<p></p>", "")
|
||||
|
||||
msgList = addMETri(msgList, "<", "<")
|
||||
msgList = addMETri(msgList, ">", ">")
|
||||
msgList = addMETri(msgList, "<meow>", "<meow>")
|
||||
msgList = addMETri(msgList, "<", "&lt;")
|
||||
|
||||
// Note: strings.TrimSpace strips newlines, if there's nothing before or after them
|
||||
msgList = addMETri(msgList, "<br>", "")
|
||||
msgList = addMETri(msgList, "<br />", "")
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
'use strict';
|
||||
var formVars = {};
|
||||
var tmplInits = {};
|
||||
var tmplPhrases = [];
|
||||
var tmplPhrases = []; // [key] array of phrases indexed by order of use
|
||||
var phraseBox = {};
|
||||
var alertList = [];
|
||||
var alertCount = 0;
|
||||
var moreTopicCount = 0;
|
||||
var conn;
|
||||
var selectedTopics = [];
|
||||
var attachItemCallback = function(){}
|
||||
|
@ -214,8 +216,8 @@ function runWebSockets() {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Fix the data races in this code
|
||||
if ("msg" in data) {
|
||||
// TODO: Fix the data race where the alert template hasn't been loaded yet
|
||||
wsAlertEvent(data);
|
||||
} else if("Topics" in data) {
|
||||
console.log("topic in data");
|
||||
|
@ -225,11 +227,27 @@ function runWebSockets() {
|
|||
console.log("empty topic list");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Fix the data race where the function hasn't been loaded yet
|
||||
let renTopic = Template_topics_topic(topic);
|
||||
$(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe");
|
||||
|
||||
let node = $(renTopic);
|
||||
node.addClass("new_item");
|
||||
node.addClass("new_item hide_ajax_topic");
|
||||
console.log("Prepending to topic list");
|
||||
$(".topic_list").prepend(node);
|
||||
moreTopicCount++;
|
||||
|
||||
let moreTopicBlocks = document.getElementsByClassName("more_topic_block_initial");
|
||||
for(let i = 0; i < moreTopicBlocks.length; i++) {
|
||||
let moreTopicBlock = moreTopicBlocks[i];
|
||||
moreTopicBlock.classList.remove("more_topic_block_initial");
|
||||
moreTopicBlock.classList.add("more_topic_block_active");
|
||||
|
||||
console.log("phraseBox:",phraseBox);
|
||||
let msgBox = moreTopicBlock.getElementsByClassName("more_topics")[0];
|
||||
msgBox.innerText = phraseBox["topic_list"]["topic_list.changed_topics"].replace("%d",moreTopicCount);
|
||||
}
|
||||
} else {
|
||||
console.log("unknown message");
|
||||
console.log(data);
|
||||
|
@ -278,9 +296,11 @@ function DoNothingButPassBack(item) {
|
|||
}
|
||||
|
||||
function fetchPhrases() {
|
||||
fetch("//" +siteURL+"/api/phrases/?query=status")
|
||||
fetch("//" +siteURL+"/api/phrases/?query=status,topic_list")
|
||||
.then((resp) => resp.json())
|
||||
.then((data) => {
|
||||
console.log("loaded phrase endpoint data");
|
||||
console.log("data:",data);
|
||||
Object.keys(tmplInits).forEach((key) => {
|
||||
let phrases = [];
|
||||
let tmplInit = tmplInits[key];
|
||||
|
@ -291,7 +311,20 @@ function fetchPhrases() {
|
|||
console.log("key:",key);
|
||||
console.log("phrases:",phrases);
|
||||
tmplPhrases[key] = phrases;
|
||||
})
|
||||
});
|
||||
|
||||
let prefixes = {};
|
||||
Object.keys(data).forEach((key) => {
|
||||
let prefix = key.split(".")[0];
|
||||
if(prefixes[prefix]===undefined) {
|
||||
prefixes[prefix] = {};
|
||||
}
|
||||
prefixes[prefix][key] = data[key];
|
||||
});
|
||||
Object.keys(prefixes).forEach((prefix) => {
|
||||
console.log("adding phrase prefix '"+prefix+"' to box");
|
||||
phraseBox[prefix] = prefixes[prefix];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -319,6 +352,21 @@ $(document).ready(function(){
|
|||
if(window["WebSocket"]) runWebSockets();
|
||||
else conn = false;
|
||||
|
||||
$(".more_topics").click((event) => {
|
||||
event.preventDefault();
|
||||
let moreTopicBlocks = document.getElementsByClassName("more_topic_block_active");
|
||||
for(let i = 0; i < moreTopicBlocks.length; i++) {
|
||||
let moreTopicBlock = moreTopicBlocks[i];
|
||||
moreTopicBlock.classList.remove("more_topic_block_active");
|
||||
moreTopicBlock.classList.add("more_topic_block_initial");
|
||||
}
|
||||
$(".ajax_topic_dupe").fadeOut("slow", function(){
|
||||
$(this).remove();
|
||||
});
|
||||
$(".hide_ajax_topic").removeClass("hide_ajax_topic"); // TODO: Do Fade
|
||||
moreTopicCount = 0;
|
||||
})
|
||||
|
||||
$(".add_like").click(function(event) {
|
||||
event.preventDefault();
|
||||
let likeButton = this;
|
||||
|
@ -596,7 +644,8 @@ $(document).ready(function(){
|
|||
|
||||
let reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
crypto.subtle.digest('SHA-256',e.target.result).then(function(hash) {
|
||||
crypto.subtle.digest('SHA-256',e.target.result)
|
||||
.then(function(hash) {
|
||||
const hashArray = Array.from(new Uint8Array(hash))
|
||||
return hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('')
|
||||
}).then(function(hash) {
|
||||
|
@ -619,6 +668,7 @@ $(document).ready(function(){
|
|||
reader.readAsDataURL(files[i]);
|
||||
}
|
||||
if(totalSize>maxRequestSize) {
|
||||
// TODO: Use a notice instead
|
||||
alert("You can't upload this much data at once, max: " + maxRequestSize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
<div class="optbox">
|
||||
{{if .CurrentUser.Perms.CreateTopic}}
|
||||
<div class="pre_opt auto_hide"></div>
|
||||
<div class="opt create_topic_opt" title="{{lang "topic_list_create_topic_tooltip"}}" aria-label="{{lang "topic_list_create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/{{.Forum.ID}}"></a></div>
|
||||
<div class="opt create_topic_opt" title="{{lang "topic_list.create_topic_tooltip"}}" aria-label="{{lang "topic_list.create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/{{.Forum.ID}}"></a></div>
|
||||
{{/** TODO: Add a permissions check for this **/}}
|
||||
<div class="opt mod_opt" title="{{lang "topic_list_moderate_tooltip"}}">
|
||||
<a class="moderate_link" href="#" aria-label="{{lang "topic_list_moderate_aria"}}"></a>
|
||||
<div class="opt mod_opt" title="{{lang "topic_list.moderate_tooltip"}}">
|
||||
<a class="moderate_link" href="#" aria-label="{{lang "topic_list.moderate_aria"}}"></a>
|
||||
</div>
|
||||
{{else}}<div class="opt locked_opt" title="{{lang "forum_locked_tooltip"}}" aria-label="{{lang "forum_locked_aria"}}"><a></a></div>{{end}}
|
||||
</div>
|
||||
|
@ -26,15 +26,15 @@
|
|||
<div class="mod_floater auto_hide">
|
||||
<form method="post">
|
||||
<div class="mod_floater_head">
|
||||
<span>{{lang "topic_list_what_to_do"}}</span>
|
||||
<span>{{lang "topic_list.what_to_do"}}</span>
|
||||
</div>
|
||||
<div class="mod_floater_body">
|
||||
<select class="mod_floater_options">
|
||||
<option val="delete">{{lang "topic_list_moderate_delete"}}</option>
|
||||
<option val="lock">{{lang "topic_list_moderate_lock"}}</option>
|
||||
<option val="move">{{lang "topic_list_moderate_move"}}</option>
|
||||
<option val="delete">{{lang "topic_list.moderate_delete"}}</option>
|
||||
<option val="lock">{{lang "topic_list.moderate_lock"}}</option>
|
||||
<option val="move">{{lang "topic_list.moderate_move"}}</option>
|
||||
</select>
|
||||
<button>{{lang "topic_list_moderate_run"}}</button>
|
||||
<button>{{lang "topic_list.moderate_run"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -20,8 +20,11 @@
|
|||
<script type="text/javascript" src="/static/global.js"></script>
|
||||
<meta name="viewport" content="width=device-width,initial-scale = 1.0, maximum-scale=1.0,user-scalable=no" />
|
||||
{{if .Header.MetaDesc}}<meta name="description" content="{{.Header.MetaDesc}}" />{{end}}
|
||||
{{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="{{.Header.Site.Name}}">
|
||||
<meta property="og:title" content="{{.Title}} | {{.Header.Site.Name}}">
|
||||
<meta name="twitter:title" content="{{.Title}} | {{.Header.Site.Name}}" />
|
||||
</head>
|
||||
<body>
|
||||
{{if not .CurrentUser.IsSuperMod}}<style>.supermod_only { display: none !important; }</style>{{end}}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
<div class="optbox">
|
||||
{{if .ForumList}}
|
||||
<div class="pre_opt auto_hide"></div>
|
||||
<div class="opt create_topic_opt" title="{{lang "topic_list_create_topic_tooltip"}}" aria-label="{{lang "topic_list_create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/"></a></div>
|
||||
<div class="opt create_topic_opt" title="{{lang "topic_list.create_topic_tooltip"}}" aria-label="{{lang "topic_list.create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/"></a></div>
|
||||
{{/** TODO: Add a permissions check for this **/}}
|
||||
<div class="opt mod_opt" title="{{lang "topic_list_moderate_tooltip"}}">
|
||||
<a class="moderate_link" href="#" aria-label="{{lang "topic_list_moderate_aria"}}"></a>
|
||||
<div class="opt mod_opt" title="{{lang "topic_list.moderate_tooltip"}}">
|
||||
<a class="moderate_link" href="#" aria-label="{{lang "topic_list.moderate_aria"}}"></a>
|
||||
</div>
|
||||
{{else}}<div class="opt locked_opt" title="{{lang "topics_locked_tooltip"}}" aria-label="{{lang "topics_locked_aria"}}"><a></a></div>{{end}}
|
||||
</div>
|
||||
|
@ -23,15 +23,15 @@
|
|||
<div class="mod_floater auto_hide">
|
||||
<form method="post">
|
||||
<div class="mod_floater_head">
|
||||
<span>{{lang "topic_list_what_to_do"}}</span>
|
||||
<span>{{lang "topic_list.what_to_do"}}</span>
|
||||
</div>
|
||||
<div class="mod_floater_body">
|
||||
<select class="mod_floater_options">
|
||||
<option val="delete">{{lang "topic_list_moderate_delete"}}</option>
|
||||
<option val="lock">{{lang "topic_list_moderate_lock"}}</option>
|
||||
<option val="move">{{lang "topic_list_moderate_move"}}</option>
|
||||
<option val="delete">{{lang "topic_list.moderate_delete"}}</option>
|
||||
<option val="lock">{{lang "topic_list.moderate_lock"}}</option>
|
||||
<option val="move">{{lang "topic_list.moderate_move"}}</option>
|
||||
</select>
|
||||
<button class="mod_floater_submit">{{lang "topic_list_moderate_run"}}</button>
|
||||
<button class="mod_floater_submit">{{lang "topic_list.moderate_run"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<form action="/topic/move/submit/?session={{.CurrentUser.Session}}" method="post">
|
||||
<input id="mover_fid" name="fid" value="0" type="hidden" />
|
||||
<div class="pane_header">
|
||||
<h3>{{lang "topic_list_move_head"}}</h3>
|
||||
<h3>{{lang "topic_list.move_head"}}</h3>
|
||||
</div>
|
||||
<div class="pane_body">
|
||||
<div class="pane_table">
|
||||
|
@ -51,7 +51,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="pane_buttons">
|
||||
<button id="mover_submit">{{lang "topic_list_move_button"}}</button>
|
||||
<button id="mover_submit">{{lang "topic_list.move_button"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -101,6 +101,9 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div class="rowblock more_topic_block more_topic_block_initial">
|
||||
<div class="rowitem rowmsg"><a href="" class="more_topics"></a></div>
|
||||
</div>
|
||||
<div id="topic_list" class="rowblock topic_list" aria-label="{{lang "topics_list_aria"}}">
|
||||
{{range .TopicList}}{{template "topics_topic.html" . }}{{else}}<div class="rowitem passive rowmsg">{{lang "topics_no_topics"}}{{if .CurrentUser.Perms.CreateTopic}} <a href="/topics/create/">{{lang "topics_start_one"}}</a>{{end}}</div>{{end}}
|
||||
</div>
|
||||
|
|
|
@ -698,9 +698,16 @@ textarea {
|
|||
background-color: rgb(239, 255, 255);
|
||||
border: 1px solid rgb(187, 217, 217);
|
||||
border-bottom: 2px solid rgb(187, 217, 217);
|
||||
border-left: none;
|
||||
}
|
||||
.topic_row.new_item .topic_left {
|
||||
border-right: none;
|
||||
}
|
||||
.topic_row.new_item .topic_right {
|
||||
border-left: none;
|
||||
}
|
||||
.hide_ajax_topic {
|
||||
display: none !important;
|
||||
}
|
||||
.topic_middle {
|
||||
display: none;
|
||||
}
|
||||
|
@ -896,6 +903,13 @@ textarea {
|
|||
}
|
||||
}
|
||||
|
||||
.more_topic_block_initial {
|
||||
display: none;
|
||||
}
|
||||
.more_topic_block_active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.forum_list, .post_container {
|
||||
border: none;
|
||||
}
|
||||
|
|
|
@ -236,6 +236,14 @@ h1, h3 {
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* TODO: Make a generic version of this so that we can have more blocks which are initially hidden but flip over to visible under certain conditions */
|
||||
.more_topic_block_initial {
|
||||
display: none;
|
||||
}
|
||||
.more_topic_block_active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, select, button, .formbutton, textarea {
|
||||
border-radius: 3px;
|
||||
background: rgb(90,90,90);
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
{
|
||||
"Name": "nox",
|
||||
"FriendlyName": "Nox",
|
||||
"FriendlyName": "Nox (Incomplete)",
|
||||
"Version": "0.0.1",
|
||||
"Creator": "Azareal",
|
||||
"URL": "github.com/Azareal/Gosora",
|
||||
"Tag": "WIP",
|
||||
"HideFromThemes":true,
|
||||
"Docks":["topMenu","rightSidebar","footer"],
|
||||
"MapTmplToDock": {
|
||||
"rightOfNav": {
|
||||
"File": "./templates/userDock.html"
|
||||
}
|
||||
},
|
||||
"Templates": [
|
||||
{
|
||||
"Name": "topic",
|
||||
|
|
|
@ -841,6 +841,13 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.more_topic_block_initial {
|
||||
display: none;
|
||||
}
|
||||
.more_topic_block_active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.topic_name_input {
|
||||
width: 100%;
|
||||
margin-right: 10px;
|
||||
|
|
|
@ -489,6 +489,13 @@ li a {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.more_topic_block_initial {
|
||||
display: none;
|
||||
}
|
||||
.more_topic_block_active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.postImage {
|
||||
max-width: 100%;
|
||||
max-height: 200px;
|
||||
|
|
|
@ -498,6 +498,13 @@ input, select {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.more_topic_block_initial {
|
||||
display: none;
|
||||
}
|
||||
.more_topic_block_active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.postImage {
|
||||
max-width: 100%;
|
||||
max-height: 200px;
|
||||
|
|
Loading…
Reference in New Issue