Show comments
Show comments on a story's short description, and automatically load comments when reading a story.
This commit is contained in:
parent
443a6331e6
commit
652e673d39
|
@ -5,7 +5,6 @@ Notably, holds a connection to the open sqlite3 database in .conn
|
||||||
local sql = require("lsqlite3")
|
local sql = require("lsqlite3")
|
||||||
|
|
||||||
local queries = require("queries")
|
local queries = require("queries")
|
||||||
local util = require("util")
|
|
||||||
local config = require("config")
|
local config = require("config")
|
||||||
|
|
||||||
local db = {}
|
local db = {}
|
||||||
|
@ -16,7 +15,11 @@ message on fail, and returns true on success.
|
||||||
]]
|
]]
|
||||||
function db.sqlassert(r, errcode, err)
|
function db.sqlassert(r, errcode, err)
|
||||||
if not r then
|
if not r then
|
||||||
error(string.format("%d: %s",errcode, err))
|
if err then
|
||||||
|
error(string.format("%d: %s",errcode, err))
|
||||||
|
elseif errcode then
|
||||||
|
error(string.format("%d: %s",errcode, db.conn:errmsg()))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return r
|
return r
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,21 +15,21 @@ local stmnt_index, stmnt_author, stmnt_author_bio
|
||||||
|
|
||||||
local oldconfigure = configure
|
local oldconfigure = configure
|
||||||
function configure(...)
|
function configure(...)
|
||||||
stmnt_index = assert(db.conn:prepare(queries.select_site_index))
|
stmnt_index = db.sqlassert(db.conn:prepare(queries.select_site_index))
|
||||||
--TODO: actually let authors edit their bio
|
--TODO: actually let authors edit their bio
|
||||||
stmnt_author_bio = assert(db.conn:prepare([[
|
stmnt_author_bio = db.sqlassert(db.conn:prepare([[
|
||||||
SELECT authors.biography FROM authors WHERE authors.name = :author;
|
SELECT authors.biography FROM authors WHERE authors.name = :author;
|
||||||
]]))
|
]]))
|
||||||
stmnt_author = assert(db.conn:prepare(queries.select_author_index))
|
stmnt_author = db.sqlassert(db.conn:prepare(queries.select_author_index))
|
||||||
return oldconfigure(...)
|
return oldconfigure(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_site_home(req, loggedin)
|
local function get_site_home(req, loggedin)
|
||||||
log(LOG_DEBUG,"Cache miss, rendering site index")
|
log(LOG_DEBUG,"Cache miss, rendering site index")
|
||||||
stmnt_index:bind_names{}
|
stmnt_index:bind_names{offset=0}
|
||||||
local latest = {}
|
local latest = {}
|
||||||
for idr, title, iar, dater, author, hits in db.sql_rows(stmnt_index) do
|
for idr, title, iar, dater, author, hits, cmts in db.sql_rows(stmnt_index) do
|
||||||
table.insert(latest,{
|
local story = {
|
||||||
url = util.encode_id(idr),
|
url = util.encode_id(idr),
|
||||||
title = title,
|
title = title,
|
||||||
isanon = tonumber(iar) == 1,
|
isanon = tonumber(iar) == 1,
|
||||||
|
@ -37,12 +37,19 @@ local function get_site_home(req, loggedin)
|
||||||
author = author,
|
author = author,
|
||||||
tags = libtags.get(idr),
|
tags = libtags.get(idr),
|
||||||
hits = hits,
|
hits = hits,
|
||||||
})
|
ncomments = cmts
|
||||||
|
}
|
||||||
|
table.insert(latest,story)
|
||||||
|
|
||||||
end
|
end
|
||||||
return pages.index{
|
return pages.index{
|
||||||
domain = config.domain,
|
domain = config.domain,
|
||||||
stories = latest,
|
stories = latest,
|
||||||
loggedin = loggedin
|
loggedin = loggedin,
|
||||||
|
extra_load = {
|
||||||
|
'<script src="/_js/index_scroll.js"></script>'
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local function get_author_home(req, loggedin)
|
local function get_author_home(req, loggedin)
|
||||||
|
@ -71,7 +78,7 @@ local function get_author_home(req, loggedin)
|
||||||
stmnt_author_bio:reset()
|
stmnt_author_bio:reset()
|
||||||
stmnt_author:bind_names{author=subdomain}
|
stmnt_author:bind_names{author=subdomain}
|
||||||
local stories = {}
|
local stories = {}
|
||||||
for id, title, time, hits, unlisted, hash in db.sql_rows(stmnt_author) do
|
for id, title, time, hits, unlisted, hash, cmts in db.sql_rows(stmnt_author) do
|
||||||
if unlisted == 1 and author == subdomain then
|
if unlisted == 1 and author == subdomain then
|
||||||
local url = util.encode_id(id) .. "?pwd=" .. util.encode_unlisted(hash)
|
local url = util.encode_id(id) .. "?pwd=" .. util.encode_unlisted(hash)
|
||||||
table.insert(stories,{
|
table.insert(stories,{
|
||||||
|
@ -82,6 +89,7 @@ local function get_author_home(req, loggedin)
|
||||||
tags = libtags.get(id),
|
tags = libtags.get(id),
|
||||||
hits = hits,
|
hits = hits,
|
||||||
unlisted = true,
|
unlisted = true,
|
||||||
|
ncomments = cmts
|
||||||
})
|
})
|
||||||
elseif unlisted == 0 then
|
elseif unlisted == 0 then
|
||||||
table.insert(stories,{
|
table.insert(stories,{
|
||||||
|
@ -92,6 +100,7 @@ local function get_author_home(req, loggedin)
|
||||||
tags = libtags.get(id),
|
tags = libtags.get(id),
|
||||||
hits = hits,
|
hits = hits,
|
||||||
unlisted = false,
|
unlisted = false,
|
||||||
|
ncomments = cmts
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,6 +24,7 @@ local function preview_post(req)
|
||||||
idp = "preview",
|
idp = "preview",
|
||||||
text = parsed,
|
text = parsed,
|
||||||
tags = tags,
|
tags = tags,
|
||||||
|
comments = {}
|
||||||
}
|
}
|
||||||
http_response(req,200,ret)
|
http_response(req,200,ret)
|
||||||
end
|
end
|
||||||
|
|
|
@ -73,24 +73,6 @@ local function populate_ps_story(req,ps)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
|
||||||
Get the comments for a story
|
|
||||||
]]
|
|
||||||
local function get_comments(req,ps)
|
|
||||||
stmnt_comments:bind_names{
|
|
||||||
id = ps.storyid
|
|
||||||
}
|
|
||||||
local comments = {}
|
|
||||||
for com_author, com_isanon, com_text in db.sql_rows(stmnt_comments) do
|
|
||||||
table.insert(comments,{
|
|
||||||
author = com_author,
|
|
||||||
isanon = com_isanon == 1, --int to boolean
|
|
||||||
text = com_text
|
|
||||||
})
|
|
||||||
end
|
|
||||||
return comments
|
|
||||||
end
|
|
||||||
|
|
||||||
local function read_get(req)
|
local function read_get(req)
|
||||||
--Pages settings
|
--Pages settings
|
||||||
local ps = {
|
local ps = {
|
||||||
|
@ -130,9 +112,9 @@ local function read_get(req)
|
||||||
|
|
||||||
--If we need to show comments
|
--If we need to show comments
|
||||||
http_request_populate_qs(req)
|
http_request_populate_qs(req)
|
||||||
ps.show_comments = http_argument_get_string(req,"comments")
|
ps.show_comments = true
|
||||||
if ps.show_comments then
|
if ps.show_comments then
|
||||||
ps.comments = get_comments(req,ps)
|
ps.comments = util.get_comments(ps.storyid)
|
||||||
end
|
end
|
||||||
|
|
||||||
--If this post is unlisted, get the hash
|
--If this post is unlisted, get the hash
|
||||||
|
|
|
@ -2,8 +2,19 @@
|
||||||
local sql = require("lsqlite3")
|
local sql = require("lsqlite3")
|
||||||
local config = require("config")
|
local config = require("config")
|
||||||
local types = require("types")
|
local types = require("types")
|
||||||
|
local db = require("db")
|
||||||
|
local queries = require("queries")
|
||||||
|
|
||||||
local util = {}
|
local util = {}
|
||||||
|
|
||||||
|
|
||||||
|
local stmnt_comments
|
||||||
|
local oldconfigure = configure
|
||||||
|
function configure(...)
|
||||||
|
stmnt_comments = assert(db.conn:prepare(queries.select_comments))
|
||||||
|
return oldconfigure(...)
|
||||||
|
end
|
||||||
|
|
||||||
--see https://perishablepress.com/stop-using-unsafe-characters-in-urls/
|
--see https://perishablepress.com/stop-using-unsafe-characters-in-urls/
|
||||||
--no underscore because we use that for our operative pages
|
--no underscore because we use that for our operative pages
|
||||||
local url_characters =
|
local url_characters =
|
||||||
|
@ -147,6 +158,32 @@ function util.parse_tags(str)
|
||||||
return tags
|
return tags
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Get the comments for a story
|
||||||
|
|
||||||
|
Comments are a table with the structure:
|
||||||
|
comment :: table {
|
||||||
|
author :: string - The author's text name
|
||||||
|
isanon :: boolean - True if the author is anon (author string will be "Anonymous")
|
||||||
|
text :: string - The text of the comment
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
function util.get_comments(sid)
|
||||||
|
stmnt_comments:bind_names{
|
||||||
|
id = sid
|
||||||
|
}
|
||||||
|
local comments = {}
|
||||||
|
for com_author, com_isanon, com_text in db.sql_rows(stmnt_comments) do
|
||||||
|
table.insert(comments,{
|
||||||
|
author = com_author,
|
||||||
|
isanon = com_isanon == 1, --int to boolean
|
||||||
|
text = com_text
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return comments
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
if config.debugging then
|
if config.debugging then
|
||||||
function util.checktypes(...)
|
function util.checktypes(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</td><td>
|
</td><td>
|
||||||
<%= story.hits %> hits
|
<%= story.hits %> hits
|
||||||
|
</td><td>
|
||||||
|
<%= story.ncomments %> comments
|
||||||
</td><td>
|
</td><td>
|
||||||
<ul class="row tag-list">
|
<ul class="row tag-list">
|
||||||
<% for i = 1,math.min(#story.tags, 5) do %>
|
<% for i = 1,math.min(#story.tags, 5) do %>
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
<p><%= views %> Hits</p>
|
<p><%= views %> Hits, <%= #comments %> Comments</p>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<% for _, spec in ipairs(api.get.page_reader(getfenv(1))) do %>
|
<% for _, spec in ipairs(api.get.page_reader(getfenv(1))) do %>
|
||||||
|
@ -49,46 +49,36 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if not show_comments then -%>
|
<form action="https://<%= domain %>/<%= short %>" method="POST">
|
||||||
<form action="https://<%= domain %>/<%= short %>"><fieldset>
|
<% if unlisted then %>
|
||||||
<input type="hidden" name="comments" value="1">
|
<input type="hidden" name="pwd" value="<%= hashstr %>"/>
|
||||||
<% if unlisted then %>
|
|
||||||
<input type="hidden" name="pwd" value="<%= hashstr %>"/>
|
|
||||||
<% end %>
|
|
||||||
<input type="submit" value="load comments" class="button">
|
|
||||||
</fieldset></form>
|
|
||||||
<% else %>
|
|
||||||
<form action="https://<%= domain %>/<%= short %>" method="POST">
|
|
||||||
<% if unlisted then %>
|
|
||||||
<input type="hidden" name="pwd" value="<%= hashstr %>"/>
|
|
||||||
<% end %>
|
|
||||||
<textarea name="text" cols=60 rows=10 class="column"></textarea>
|
|
||||||
</div><% if iam then %>
|
|
||||||
<select id="postas" name="postas">
|
|
||||||
<option value="Anonymous">Anonymous</option>
|
|
||||||
<option value="<%= iam %>"><%= iam %></option>
|
|
||||||
</select>
|
|
||||||
<input type="submit" value="post" class="button">
|
|
||||||
<% else %>
|
|
||||||
<input type="hidden" name="postas" value="Anonymous">
|
|
||||||
<input type="submit" value="post" class="button">
|
|
||||||
<% end %>
|
|
||||||
</form>
|
|
||||||
<% if comments and #comments == 0 then %>
|
|
||||||
<p><i>No comments yet</i></p>
|
|
||||||
<% else %>
|
|
||||||
<section>
|
|
||||||
<% for _,comment in pairs(comments) do %>
|
|
||||||
<article>
|
|
||||||
<% if comment.isanon then %>
|
|
||||||
<p><b>Anonymous</b></p>
|
|
||||||
<% else %>
|
|
||||||
<p><b><%= comment.author %></b></p>
|
|
||||||
<% end %>
|
|
||||||
<p><%= comment.text %></p>
|
|
||||||
</article>
|
|
||||||
<% end %>
|
|
||||||
</section>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<textarea name="text" cols=60 rows=10 class="column"></textarea>
|
||||||
|
</div><% if iam then %>
|
||||||
|
<select id="postas" name="postas">
|
||||||
|
<option value="Anonymous">Anonymous</option>
|
||||||
|
<option value="<%= iam %>"><%= iam %></option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" value="post" class="button">
|
||||||
|
<% else %>
|
||||||
|
<input type="hidden" name="postas" value="Anonymous">
|
||||||
|
<input type="submit" value="post" class="button">
|
||||||
|
<% end %>
|
||||||
|
</form>
|
||||||
|
<% if comments and #comments == 0 then %>
|
||||||
|
<p><i>No comments yet</i></p>
|
||||||
|
<% else %>
|
||||||
|
<section>
|
||||||
|
<% for _,comment in pairs(comments) do %>
|
||||||
|
<article>
|
||||||
|
<% if comment.isanon then %>
|
||||||
|
<p><b>Anonymous</b></p>
|
||||||
|
<% else %>
|
||||||
|
<p><b><%= comment.author %></b></p>
|
||||||
|
<% end %>
|
||||||
|
<p><%= comment.text %></p>
|
||||||
|
</article>
|
||||||
|
<% end %>
|
||||||
|
</section>
|
||||||
<% end %>
|
<% end %>
|
||||||
<{system cat src/pages/parts/footer.etlua}>
|
<{system cat src/pages/parts/footer.etlua}>
|
||||||
|
|
|
@ -6,13 +6,17 @@ SELECT
|
||||||
posts.post_time,
|
posts.post_time,
|
||||||
posts.views,
|
posts.views,
|
||||||
posts.unlisted,
|
posts.unlisted,
|
||||||
posts.hash
|
posts.hash,
|
||||||
|
COUNT(comments.id)
|
||||||
FROM
|
FROM
|
||||||
posts,
|
posts,
|
||||||
authors
|
authors
|
||||||
|
LEFT JOIN comments ON comments.postid = posts.id
|
||||||
WHERE
|
WHERE
|
||||||
posts.isanon = 0 AND
|
posts.isanon = 0 AND
|
||||||
posts.authorid = authors.id AND
|
posts.authorid = authors.id AND
|
||||||
authors.name = :author
|
authors.name = :author
|
||||||
|
GROUP BY
|
||||||
|
posts.id
|
||||||
ORDER BY
|
ORDER BY
|
||||||
posts.post_time DESC
|
posts.post_time DESC
|
||||||
|
|
|
@ -5,13 +5,18 @@ SELECT
|
||||||
posts.isanon,
|
posts.isanon,
|
||||||
posts.post_time,
|
posts.post_time,
|
||||||
authors.name,
|
authors.name,
|
||||||
posts.views
|
posts.views,
|
||||||
|
COUNT(comments.id)
|
||||||
FROM
|
FROM
|
||||||
posts,
|
posts,
|
||||||
authors
|
authors
|
||||||
|
LEFT JOIN comments ON comments.postid = posts.id
|
||||||
WHERE
|
WHERE
|
||||||
posts.authorid = authors.id AND
|
posts.authorid = authors.id AND
|
||||||
posts.unlisted = 0
|
posts.unlisted = 0
|
||||||
|
GROUP BY
|
||||||
|
posts.id
|
||||||
ORDER BY
|
ORDER BY
|
||||||
posts.post_time DESC
|
posts.post_time DESC
|
||||||
LIMIT 50;
|
LIMIT 50
|
||||||
|
OFFSET :offset;
|
||||||
|
|
Loading…
Reference in New Issue