add threads n posts
This commit is contained in:
parent
f5485702a8
commit
4039d6d299
112
apps/threads.lua
112
apps/threads.lua
@ -1,7 +1,119 @@
|
||||
local app = require("lapis").Application()
|
||||
local lapis_util = require("lapis.util")
|
||||
|
||||
local db = require("lapis.db")
|
||||
local util = require("util")
|
||||
|
||||
local models = require("models")
|
||||
local Topics = models.Topics
|
||||
local Threads = models.Threads
|
||||
local Posts = models.Posts
|
||||
|
||||
app:get("thread_create", "/create", function(self)
|
||||
local user = util.get_logged_in_user(self)
|
||||
if not user then
|
||||
self.session.flash = {error = "You must be logged in to perform this action."}
|
||||
return {redirect_to = self:url_for("user_login")}
|
||||
end
|
||||
local all_topics = db.query("select * from topics limit 25;")
|
||||
if #all_topics == 0 then
|
||||
return "how did you get here?"
|
||||
end
|
||||
self.all_topics = all_topics
|
||||
return {render = "threads.create"}
|
||||
end)
|
||||
|
||||
app:post("thread_create", "/create", function(self)
|
||||
local user = util.get_logged_in_user(self)
|
||||
if not user then
|
||||
self.session.flash = {error = "You must be logged in to perform this action."}
|
||||
return {redirect_to = self:url_for("user_login")}
|
||||
end
|
||||
local topic = Topics:find(self.params.topic_id)
|
||||
if not topic then
|
||||
return {redirect_to = self:url_for("topics")}
|
||||
end
|
||||
|
||||
local title = lapis_util.trim(self.params.title)
|
||||
local time = os.time()
|
||||
local slug = lapis_util.slugify(title) .. "-" .. time
|
||||
|
||||
local post_content = self.params.initial_post
|
||||
|
||||
local thread = Threads:create({
|
||||
topic_id = topic.id,
|
||||
user_id = user.id,
|
||||
title = title,
|
||||
slug = slug,
|
||||
created_at = time,
|
||||
})
|
||||
|
||||
local post = util.create_post(thread.id, user.id, post_content)
|
||||
if not post then
|
||||
return {redirect_to = self:url_for("topics")}
|
||||
end
|
||||
|
||||
return {redirect_to = self:url_for("thread", {slug = slug})}
|
||||
end)
|
||||
|
||||
app:get("thread", "/:slug", function(self)
|
||||
local thread = Threads:find({
|
||||
slug = self.params.slug
|
||||
})
|
||||
if not thread then
|
||||
return {status = 404}
|
||||
end
|
||||
self.thread = thread
|
||||
local posts = db.query([[
|
||||
SELECT
|
||||
posts.id, post_history.content, users.username, avatars.file_path AS avatar_path
|
||||
FROM
|
||||
posts
|
||||
JOIN
|
||||
post_history ON posts.current_revision_id = post_history.id
|
||||
JOIN
|
||||
users ON posts.user_id = users.id
|
||||
LEFT JOIN
|
||||
avatars ON users.avatar_id = avatars.id
|
||||
WHERE
|
||||
posts.thread_id = ? and posts.id > ?
|
||||
ORDER BY
|
||||
posts.created_at ASC
|
||||
LIMIT 20
|
||||
]], thread.id, tonumber(self.params.cursor or 0))
|
||||
self.user = util.get_logged_in_user_or_transient(self)
|
||||
self.posts = posts
|
||||
self.next_cursor = #posts > 0 and posts[#posts].id or nil
|
||||
return {render = "threads.thread"}
|
||||
end)
|
||||
|
||||
app:post("thread", "/:slug", function(self)
|
||||
local thread = Threads:find({
|
||||
slug = self.params.slug
|
||||
})
|
||||
if not thread then
|
||||
return {redirect_to = self:url_for("all_topics")}
|
||||
end
|
||||
local user = util.get_logged_in_user(self)
|
||||
if not user then
|
||||
return {redirect_to = self:url_for("all_topics")}
|
||||
end
|
||||
|
||||
if user:is_guest() then
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug})}
|
||||
end
|
||||
|
||||
if util.is_thread_locked(thread) and not user:is_admin() then
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug})}
|
||||
end
|
||||
|
||||
local post_content = self.params.post_content
|
||||
local post = util.create_post(thread.id, user.id, post_content)
|
||||
if not post then
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug})}
|
||||
end
|
||||
|
||||
return {redirect_to = self:url_for("thread", {slug = thread.slug})}
|
||||
end)
|
||||
|
||||
return app
|
||||
|
@ -19,7 +19,7 @@ local ThreadCreateError = {
|
||||
TOPIC_LOCKED = 3,
|
||||
}
|
||||
|
||||
app:get("all_topics", "/", function(self)
|
||||
app:get("all_topics", "", function(self)
|
||||
self.topic_list = db.query("select * from topics limit 25;")
|
||||
self.user = util.get_logged_in_user(self) or util.TransientUser
|
||||
return {render = "topics.topics"}
|
||||
|
@ -41,4 +41,11 @@ return {
|
||||
-- will appear on top of non-stickied threads in topic view
|
||||
schema.add_column("threads", "is_stickied", "BOOLEAN DEFAULT FALSE")
|
||||
end,
|
||||
|
||||
[5] = function ()
|
||||
db.query("CREATE INDEX idx_posts_thread ON posts(thread_id, created_at, id)")
|
||||
db.query("CREATE INDEX idx_users_avatar ON users(avatar_id)")
|
||||
db.query("CREATE INDEX idx_topics_slug ON topics(slug)")
|
||||
db.query("CREATE INDEX idx_threads_slug ON threads(slug)")
|
||||
end,
|
||||
}
|
||||
|
28
util.lua
28
util.lua
@ -4,6 +4,8 @@ local db = require("lapis.db")
|
||||
|
||||
local Avatars = require("models").Avatars
|
||||
local Users = require("models").Users
|
||||
local Posts = require("models").Posts
|
||||
local PostHistory = require("models").PostHistory
|
||||
|
||||
util.TransientUser = {
|
||||
is_admin = function (self)
|
||||
@ -15,6 +17,7 @@ util.TransientUser = {
|
||||
is_logged_in_guest = function (self)
|
||||
return false
|
||||
end,
|
||||
username = "Deleted User",
|
||||
}
|
||||
|
||||
function util.get_user_avatar_url(req, user)
|
||||
@ -94,4 +97,29 @@ function util.form_bool_to_sqlite(s)
|
||||
return util.bton(util.stob(s))
|
||||
end
|
||||
|
||||
function util.is_thread_locked(thread)
|
||||
return util.ntob(thread.is_locked)
|
||||
end
|
||||
|
||||
function util.create_post(thread_id, user_id, content)
|
||||
db.query("BEGIN")
|
||||
local post = Posts:create({
|
||||
thread_id = thread_id,
|
||||
user_id = user_id,
|
||||
current_revision_id = db.NULL,
|
||||
})
|
||||
|
||||
local revision = PostHistory:create({
|
||||
post_id = post.id,
|
||||
user_id = user_id,
|
||||
content = content,
|
||||
is_initial_revision = true,
|
||||
})
|
||||
|
||||
post:update({current_revision_id = revision.id})
|
||||
|
||||
db.query("COMMIT")
|
||||
return post
|
||||
end
|
||||
|
||||
return util
|
13
views/threads/create.etlua
Normal file
13
views/threads/create.etlua
Normal file
@ -0,0 +1,13 @@
|
||||
<h1>New thread</h1>
|
||||
<form method="post">
|
||||
<label for="topic_id">Topic:</label>
|
||||
<select name="topic_id", id="topic_id" autocomplete="off">
|
||||
<% for _, topic in ipairs(all_topics) do %>
|
||||
<option value="<%= topic.id %>" <%- params.topic_id == tostring(topic.id) and "selected" or "" %>><%= topic.name %></value>
|
||||
<% end %>
|
||||
</select><br>
|
||||
<label for="title">Thread title:</label>
|
||||
<input type="text" id="title" name="title" required><br>
|
||||
<textarea id="initial_post" name="initial_post" placeholder="Post body" required></textarea><br>
|
||||
<input type="submit" value="Create thread">
|
||||
</form>
|
20
views/threads/thread.etlua
Normal file
20
views/threads/thread.etlua
Normal file
@ -0,0 +1,20 @@
|
||||
<% for _, post in ipairs(posts) do %>
|
||||
<div>
|
||||
<img src="<%= post.avatar_path or "/avatars/default.webp" %>">
|
||||
<div><%= post.username %></div>
|
||||
<div><p><%- require("lapis.html").escape(post.content):gsub("\n", "<br>") %></p></div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if not user:is_guest() then %>
|
||||
<h1>Respond to "<%= thread.title %>"</h1>
|
||||
<form method="post">
|
||||
<textarea id="post_content" name="post_content" placeholder="Response body" required></textarea><br>
|
||||
<input type="submit" value="Reply">
|
||||
</form>
|
||||
<% end %>
|
||||
<% if next_cursor then %>
|
||||
<a href="<%= url_for('thread', {slug = thread.slug}, {cursor = next_cursor}) %>">
|
||||
Older posts →
|
||||
</a>
|
||||
<% end %>
|
@ -6,7 +6,7 @@
|
||||
<ul>
|
||||
<% for i, v in ipairs(topic_list) do %>
|
||||
<li>
|
||||
<a href=<%= v.slug %>><%= v.name %></a> - <%= v.description %>
|
||||
<a href=<%= url_for("topic", {slug = v.slug}) %>><%= v.name %></a> - <%= v.description %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
Loading…
Reference in New Issue
Block a user