add an inbox view
This commit is contained in:
parent
bd1ba6c087
commit
22526c953e
9
app.lua
9
app.lua
@ -1,5 +1,6 @@
|
||||
local lapis = require("lapis")
|
||||
local date = require("date")
|
||||
local models = require("models")
|
||||
local app = lapis.Application()
|
||||
local constants = require("constants")
|
||||
local babycode = require("lib.babycode")
|
||||
@ -47,6 +48,14 @@ local function inject_methods(req)
|
||||
req.babycode_to_html = function (_, bb)
|
||||
return babycode.to_html(bb, html_escape)
|
||||
end
|
||||
|
||||
req.get_thread_by_id = function(_, id)
|
||||
return models.Threads:find({id = id})
|
||||
end
|
||||
|
||||
req.get_post_url = function(_, id)
|
||||
return util.get_post_url(_, id)
|
||||
end
|
||||
|
||||
util.pop_infobox(req)
|
||||
end
|
||||
|
@ -238,13 +238,31 @@ app:post("thread_subscribe", "/:slug/subscribe", function(self)
|
||||
subscription:delete()
|
||||
end
|
||||
Subscriptions:create({user_id = user.id, thread_id = thread.id, last_seen = now})
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug}, {after = self.params.first_visible_post})}
|
||||
if self.params.last_visible_post then
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug}, {after = self.params.last_visible_post})}
|
||||
else
|
||||
return {redirect_to = self:url_for("user_inbox", {username = user.username})}
|
||||
end
|
||||
elseif self.params.subscribe == "unsubscribe" then
|
||||
if not subscription then
|
||||
return {status = 404}
|
||||
end
|
||||
subscription:delete()
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug}, {after = self.params.first_visible_post})}
|
||||
if self.params.last_visible_post then
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug}, {after = self.params.last_visible_post})}
|
||||
else
|
||||
return {redirect_to = self:url_for("user_inbox", {username = user.username})}
|
||||
end
|
||||
elseif self.params.subscribe == "read" then
|
||||
if not subscription then
|
||||
return {status = 404}
|
||||
end
|
||||
subscription:update({last_seen = os.time()})
|
||||
if self.params.last_visible_post then
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug}, {after = self.params.last_visible_post})}
|
||||
else
|
||||
return {redirect_to = self:url_for("user_inbox", {username = user.username})}
|
||||
end
|
||||
end
|
||||
|
||||
return {status = 400}
|
||||
|
@ -14,6 +14,7 @@ local models = require("models")
|
||||
local Users = models.Users
|
||||
local Sessions = models.Sessions
|
||||
local Avatars = models.Avatars
|
||||
local Subscriptions = models.Subscriptions
|
||||
|
||||
local function authenticate_user(user, password)
|
||||
return auth.verify(password, user.password_hash)
|
||||
@ -267,6 +268,11 @@ app:post("user_settings", "/:username/settings", function(self)
|
||||
local status = self.params.status:sub(1, 100)
|
||||
local original_sig = self.params.signature or ""
|
||||
local rendered_sig = babycode.to_html(original_sig, html_escape)
|
||||
if self.params.subscribe_by_default == "on" then
|
||||
self.session.subscribe_by_default = true
|
||||
else
|
||||
self.session.subscribe_by_default = false
|
||||
end
|
||||
|
||||
target_user:update({
|
||||
status = status,
|
||||
@ -277,6 +283,97 @@ app:post("user_settings", "/:username/settings", function(self)
|
||||
return {redirect_to = self:url_for("user_settings", {username = self.params.username})}
|
||||
end)
|
||||
|
||||
app:get("user_inbox", "/:username/inbox", function(self)
|
||||
local me = util.get_logged_in_user(self)
|
||||
if me == nil then
|
||||
util.inject_err_infobox(self, "You must be logged in to perform this action.")
|
||||
return {redirect_to = self:url_for("user_login")}
|
||||
end
|
||||
local target_user = Users:find({username = self.params.username})
|
||||
if me.id ~= target_user.id then
|
||||
return {redirect_to = self:url_for("user_inbox", {username = me.username})}
|
||||
end
|
||||
self.me = target_user
|
||||
self.page_title = "inbox"
|
||||
self.new_posts = {}
|
||||
local subscription = Subscriptions:find({user_id = me.id})
|
||||
if subscription then
|
||||
local q = [[
|
||||
WITH thread_metadata AS (
|
||||
SELECT
|
||||
posts.thread_id, threads.slug AS thread_slug, threads.title AS thread_title, COUNT(*) AS unread_count, MAX(posts.created_at) AS newest_post_time
|
||||
FROM
|
||||
posts
|
||||
LEFT JOIN
|
||||
threads ON threads.id = posts.thread_id
|
||||
LEFT JOIN
|
||||
subscriptions ON subscriptions.thread_id = posts.thread_id
|
||||
WHERE subscriptions.user_id = ? AND posts.created_at > subscriptions.last_seen
|
||||
GROUP BY posts.thread_id
|
||||
)
|
||||
|
||||
SELECT
|
||||
tm.thread_id, tm.thread_slug, tm.thread_title, tm.unread_count, tm.newest_post_time,
|
||||
|
||||
posts.id, posts.created_at, post_history.content, post_history.edited_at, users.username, users.status, avatars.file_path AS avatar_path, posts.thread_id, users.id AS user_id, post_history.original_markup, users.signature_rendered
|
||||
FROM
|
||||
thread_metadata tm
|
||||
JOIN
|
||||
posts ON posts.thread_id = tm.thread_id
|
||||
JOIN
|
||||
post_history ON posts.current_revision_id = post_history.id
|
||||
JOIN
|
||||
users ON posts.user_id = users.id
|
||||
LEFT JOIN
|
||||
threads ON threads.id = posts.thread_id
|
||||
LEFT JOIN
|
||||
avatars ON users.avatar_id = avatars.id
|
||||
LEFT JOIN
|
||||
subscriptions ON subscriptions.thread_id = posts.thread_id
|
||||
WHERE
|
||||
subscriptions.user_id = ? AND posts.created_at > subscriptions.last_seen
|
||||
ORDER BY
|
||||
tm.newest_post_time DESC, posts.created_at ASC]]
|
||||
local new_posts_raw = db.query(q, me.id, me.id)
|
||||
local threads = {}
|
||||
local current_thread_id = nil
|
||||
local current_thread_group = nil
|
||||
self.total_unreads_count = 0
|
||||
for _, row in ipairs(new_posts_raw) do
|
||||
if row.thread_id ~= current_thread_id then
|
||||
current_thread_group = {
|
||||
thread_id = row.thread_id,
|
||||
thread_title = row.thread_title,
|
||||
unread_count = row.unread_count,
|
||||
thread_slug = row.thread_slug,
|
||||
newest_post_time = row.newest_post_time,
|
||||
posts = {}
|
||||
}
|
||||
self.total_unreads_count = self.total_unreads_count + row.unread_count
|
||||
table.insert(threads, current_thread_group)
|
||||
current_thread_id = row.thread_id
|
||||
end
|
||||
---@diagnostic disable-next-line: need-check-nil
|
||||
table.insert(current_thread_group.posts, {
|
||||
id = row.id,
|
||||
created_at = row.created_at,
|
||||
content = row.content,
|
||||
edited_at = row.edited_at,
|
||||
username = row.username,
|
||||
status = row.status,
|
||||
avatar_path = row.avatar_path,
|
||||
thread_id = row.thread_id,
|
||||
user_id = row.user_id,
|
||||
original_markup = row.original_markup,
|
||||
signature_rendered = row.signature_rendered,
|
||||
})
|
||||
end
|
||||
|
||||
self.new_posts = threads
|
||||
end
|
||||
return {render = "user.inbox"}
|
||||
end)
|
||||
|
||||
app:get("user_login", "/login", function(self)
|
||||
if self.session.session_key then
|
||||
local user = util.get_logged_in_user(self)
|
||||
|
@ -679,3 +679,7 @@ ul, ol {
|
||||
.accordion-content.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inbox-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
@ -689,3 +689,7 @@ ul, ol {
|
||||
.accordion-content.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inbox-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
<% render ("views.common.babycode-editor-component", {ta_name = ta_name, prefill = prefill}) %>
|
||||
<% if not cancel_url then %>
|
||||
<span>
|
||||
<input type="checkbox" id="subscribe" name="subscribe" checked>
|
||||
<input type="checkbox" id="subscribe" name="subscribe" <%= session.subscribe_by_default and "checked" or "" %>>
|
||||
<label for="subscribe">Subscribe to thread</label>
|
||||
</span>
|
||||
<% end %>
|
||||
|
@ -9,6 +9,8 @@
|
||||
Welcome, <a href="<%= url_for("user", {username = me.username}) %>"><%= me.username %></a>
|
||||
•
|
||||
<a href="<%= url_for("user_settings", {username = me.username}) %>">Settings</a>
|
||||
•
|
||||
<a href="<%= url_for("user_inbox", {username = me.username}) %>">Inbox</a>
|
||||
<% if me:is_mod() then %>
|
||||
•
|
||||
<a href="<%= url_for("user_list") %>">User list</a>
|
||||
|
@ -18,7 +18,8 @@
|
||||
<div class="post-content-container"<%= is_latest and 'id=latest-post' or "" %>>
|
||||
<div class="post-info">
|
||||
<%
|
||||
local post_url = url_for("thread", {slug = thread.slug}, {page = page}) .. "#post-" .. post.id
|
||||
--local post_url = url_for("thread", {slug = thread.slug}, {page = page}) .. "#post-" .. post.id
|
||||
local post_url = get_post_url(post.id)
|
||||
%>
|
||||
<a href="<%= post_url %>" title="Permalink"><i>
|
||||
<% if tonumber(post.edited_at) > tonumber(post.created_at) then -%>
|
||||
@ -55,7 +56,7 @@
|
||||
<button value="<%= reply_text %>" class="reply-button">Quote</button>
|
||||
<% end %>
|
||||
<%
|
||||
local show_delete = (post.user_id == me.id and not ntob(thread.is_locked)) or me:is_mod()
|
||||
local show_delete = ((post.user_id == me.id and not ntob(thread.is_locked)) or me:is_mod()) and not no_reply
|
||||
if show_delete then
|
||||
%>
|
||||
<button class="critical post-delete-button" value="<%= post.id %>">Delete</button>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<div>
|
||||
<% if me:is_logged_in() then %>
|
||||
<form class="modform" action="<%= url_for("thread_subscribe", {slug = thread.slug}) %>" method="post">
|
||||
<input type="hidden" name="first_visible_post" value=<%= posts[1].id %>>
|
||||
<input type="hidden" name="last_visible_post" value=<%= posts[#posts].id %>>
|
||||
<input type="hidden" name="subscribe" value=<%= is_subscribed and "unsubscribe" or "subscribe" %>>
|
||||
<input type="submit" value="<%= is_subscribed and "Unsubscribe" or "Subscribe" %>">
|
||||
</form>
|
||||
|
35
views/user/inbox.etlua
Normal file
35
views/user/inbox.etlua
Normal file
@ -0,0 +1,35 @@
|
||||
<div class="darkbg">
|
||||
<h1 class="thread-title">Inbox</h1>
|
||||
</div>
|
||||
<div class="inbox-container">
|
||||
<% if #new_posts == 0 then %>
|
||||
You have no unread posts.
|
||||
<% else %>
|
||||
You have <%= total_unreads_count %> unread post<%= total_unreads_count > 1 and "s" or "" %>:
|
||||
<% for _, thread in ipairs(new_posts) do %>
|
||||
<div class="accordion">
|
||||
<div class="accordion-header">
|
||||
<button type="button" class="accordion-toggle">▼</button>
|
||||
<% local latest_post_id = thread.posts[#thread.posts].id %>
|
||||
<%
|
||||
local unread_posts_text = " (" .. thread.unread_count .. " unread post" .. (thread.unread_count > 1 and "s" or "")-- .. ")"
|
||||
%>
|
||||
<a class="accordion-title" href="<%= url_for("thread", {slug = thread.thread_slug}, {after = latest_post_id}) .. "#post-" .. latest_post_id %>" title="Jump to latest post"><%= thread.thread_title .. unread_posts_text %>, latest at <span class="timestamp" data-utc=<%= thread.newest_post_time %>><%= os.date("%c", thread.newest_post_time) %></span>)</a>
|
||||
<form action="<%= url_for("thread_subscribe", {slug = thread.thread_slug}) %>" method="post">
|
||||
<input type="hidden" name="subscribe" value="read">
|
||||
<input type="submit" value="Mark Thread as Read">
|
||||
</form>
|
||||
<form action="<%= url_for("thread_subscribe", {slug = thread.thread_slug}) %>" method="post">
|
||||
<input type="hidden" name="subscribe" value="unsubscribe">
|
||||
<input class="warn" type="submit" value="Unsubscribe">
|
||||
</form>
|
||||
</div>
|
||||
<div class="accordion-content">
|
||||
<% for _, post in ipairs(thread.posts) do %>
|
||||
<% render("views.threads.post", {post = post, edit = false, is_latest = false, no_reply = true, thread = get_thread_by_id(thread.thread_id)}) %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
@ -24,6 +24,8 @@
|
||||
<input type="text" id="status" name="status" value="<%= me.status %>" maxlength="70" placeholder="Will be shown under your username. Max 70 characters">
|
||||
<label for="babycode-content">Signature</label><br>
|
||||
<% render("views.common.babycode-editor-component", {ta_name = "signature", prefill = me.signature_original_markup, ta_placeholder = "Will be shown under each of your posts", optional = true}) %>
|
||||
<input autocomplete="off" type="checkbox" id="subscribe_by_default" name="subscribe_by_default" <%= session.subscribe_by_default and "checked" or "" %>>
|
||||
<label for="subscribe_by_default">Subscribe to thread by default when responding</label><br>
|
||||
<input type="submit" value="Save settings">
|
||||
</form>
|
||||
<form method="post" action="<%= url_for("user_change_password", {username = me.username}) %>">
|
||||
|
Loading…
Reference in New Issue
Block a user