diff --git a/app.lua b/app.lua index 6e0cd14..361fe8b 100644 --- a/app.lua +++ b/app.lua @@ -35,6 +35,7 @@ app:include("apps.users", {path = "/user"}) app:include("apps.topics", {path = "/topics"}) app:include("apps.threads", {path = "/threads"}) app:include("apps.mod", {path = "/mod"}) +app:include("apps.post", {path = "/post"}) app:get("/", function(self) return {redirect_to = self:url_for("all_topics")} diff --git a/apps/post.lua b/apps/post.lua new file mode 100644 index 0000000..83f24ec --- /dev/null +++ b/apps/post.lua @@ -0,0 +1,75 @@ +local app = require("lapis").Application() + +local db = require("lapis.db") +local constants = require("constants") + +local util = require("util") + +local models = require("models") +local Posts = models.Posts +local Threads = models.Threads + + +app:get("single_post", "/:post_id", function(self) + local query = constants.FULL_POSTS_QUERY .. "WHERE posts.id = ?" + local p = db.query(query, self.params.post_id) + if p then + self.post = p[1] + self.thread = Threads:find({id = self.post.thread_id}) + self.page_title = self.post.username .. "'s post in " .. self.thread.title + end + + return {render = "post.single-post"} +end) + +app:get("edit_post", "/:post_id/edit", function(self) + local user = util.get_logged_in_user(self) + if not user then + return {redirect_to = self:url_for"all_topics"} + end + + local editing_query = constants.FULL_POSTS_QUERY .. "WHERE posts.id = ?" + local p = db.query(editing_query, self.params.post_id) + if not p then + return {redirect_to = self:url_for"all_topics"} + end + if p[1].user_id ~= user.id then + return {redirect_to = self:url_for"all_topics"} + end + self.me = user + self.editing_post = p[1] + self.thread = Threads:find({id = self.editing_post.thread_id}) + + local thread_predicate = constants.FULL_POSTS_QUERY .. "WHERE posts.thread_id = ?\n" + + local context_prev_query = thread_predicate .. "AND posts.created_at < ? ORDER BY posts.created_at DESC LIMIT 2" + local context_next_query = thread_predicate .. "AND posts.created_at > ? ORDER BY posts.created_at ASC LIMIT 2" + + self.prev_context = db.query(context_prev_query, self.thread.id, self.editing_post.created_at) + self.next_context = db.query(context_next_query, self.thread.id, self.editing_post.created_at) + + return {render = "post.edit-post"} +end) + +app:post("edit_post", "/:post_id/edit", function(self) + local user = util.get_logged_in_user(self) + if not user then + return {redirect_to = self:url_for("all_topics")} + end + + local post = Posts:find({id = self.params.post_id}) + if not post then + return {redirect_to = self:url_for("all_topics")} + end + + if post.user_id ~= user.id then + return {redirect_to = self:url_for("all_topics")} + end + + util.update_post(post, self.params.new_content) + local thread = Threads:find({id = post.thread_id}) + local link = self:url_for("thread", {slug = thread.slug}, {after = post.id}) .. "#post-" .. post.id + return {redirect_to = link} +end) + +return app \ No newline at end of file diff --git a/apps/threads.lua b/apps/threads.lua index 871921f..ad613a2 100644 --- a/apps/threads.lua +++ b/apps/threads.lua @@ -1,5 +1,6 @@ local app = require("lapis").Application() local lapis_util = require("lapis.util") +local constants = require("constants") local db = require("lapis.db") local util = require("util") @@ -89,23 +90,9 @@ app:get("thread", "/:slug", function(self) end -- self.page = math.max(1, math.min(self.page, self.pages)) - local posts = db.query([[ - SELECT - posts.id, posts.created_at, post_history.content, post_history.edited_at, users.username, users.status, 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 = ? - ORDER BY - posts.created_at ASC - LIMIT ? OFFSET ? - ]], thread.id, POSTS_PER_PAGE, (self.page - 1) * POSTS_PER_PAGE) + local query = (constants.FULL_POSTS_QUERY .. + "WHERE posts.thread_id = ? ORDER BY posts.created_at ASC LIMIT ? OFFSET ?") + local posts = db.query(query, thread.id, POSTS_PER_PAGE, (self.page - 1) * POSTS_PER_PAGE) self.topic = Topics:find(thread.topic_id) self.me = util.get_logged_in_user_or_transient(self) self.posts = posts diff --git a/constants.lua b/constants.lua index e949217..699e5f2 100644 --- a/constants.lua +++ b/constants.lua @@ -8,6 +8,19 @@ Constants.PermissionLevel = { ADMIN = 4, } +Constants.FULL_POSTS_QUERY = [[ + SELECT + 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 + 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 +]] + Constants.PermissionLevelString = { [Constants.PermissionLevel.GUEST] = "Guest", [Constants.PermissionLevel.USER] = "User", diff --git a/data/static/style.css b/data/static/style.css index 3c40604..63aae96 100644 --- a/data/static/style.css +++ b/data/static/style.css @@ -377,3 +377,23 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus .draggable-topic.dragged { background-color: rgb(177, 206, 204.5); } + +.editing { + background-color: rgb(217.26, 220.38, 213.42); +} + +.context-explain { + margin: 20px 0; + display: flex; + justify-content: space-evenly; +} + +.post-edit-form { + display: flex; + flex-direction: column; + align-items: baseline; + height: 100%; +} +.post-edit-form > textarea { + height: 100%; +} diff --git a/sass/style.scss b/sass/style.scss index aef0f0c..d8650c4 100644 --- a/sass/style.scss +++ b/sass/style.scss @@ -381,3 +381,24 @@ input[type="text"], input[type="password"], textarea, select { background-color: $button_color; } } + +.editing { + background-color: $light; +} + +.context-explain { + margin: 20px 0; + display: flex; + justify-content: space-evenly; +} + +.post-edit-form { + display: flex; + flex-direction: column; + align-items: baseline; + height: 100%; + + &>textarea{ + height: 100%; + } +} diff --git a/util.lua b/util.lua index 232dc8a..723652a 100644 --- a/util.lua +++ b/util.lua @@ -242,6 +242,27 @@ function util.create_post(thread_id, user_id, content, markup_language) return post end +function util.update_post(post, new_content, markup_language) + markup_language = markup_language or "babycode" + db.query("BEGIN") + + local parsed_content = "" + if markup_language == "babycode" then + parsed_content = babycode.to_html(new_content, html_escape) + end + + local revision = PostHistory:create({ + post_id = post.id, + content = parsed_content, + is_initial_revision = false, + original_markup = new_content, + markup_language = markup_language + }) + + post:update({current_revision_id = revision.id}) + db.query("COMMIT") +end + function util.transfer_and_delete_user(user) local deleted_user = Users:find({ username = "DeletedUser", diff --git a/views/post/edit-post.etlua b/views/post/edit-post.etlua new file mode 100644 index 0000000..69e5c1d --- /dev/null +++ b/views/post/edit-post.etlua @@ -0,0 +1,16 @@ +<% for _, post in ipairs(prev_context) do %> + <% render("views.threads.post", {post = post, edit = false, is_latest = false, no_reply = true}) %> +<% end %> + + ↑↑↑Context↑↑↑ + +<% if infobox then %> + <% render("views.common.infobox", infobox) %> +<% end %> +<% render("views.threads.post", {post = editing_post, edit = true, is_latest = false, no_reply = true}) %> + + ↓↓↓Context↓↓↓ + +<% for _, post in ipairs(next_context) do %> + <% render("views.threads.post", {post = post, edit = false, is_latest = false, no_reply = true}) %> +<% end %> diff --git a/views/post/single-post.etlua b/views/post/single-post.etlua new file mode 100644 index 0000000..9bfe613 --- /dev/null +++ b/views/post/single-post.etlua @@ -0,0 +1,9 @@ +<% if not post then %> + <% render("views.common.infobox", {kind = constants.InfoboxKind.ERROR, msg = "Post not found"}) %> +<% else %> +