From 12269dd9b3ab210d630bb23a90a62d01a79d28c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Fri, 23 May 2025 20:41:06 +0300 Subject: [PATCH] add sorting topics view --- apps/mod.lua | 35 ++++++++++++++++++++++++----- data/static/style.css | 13 +++++++++++ js/sort-topics.js | 45 +++++++++++++++++++++++++++++++++++++ sass/style.scss | 15 +++++++++++++ views/mod/sort-topics.etlua | 19 ++++++++++++++++ views/topics/topics.etlua | 1 + 6 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 js/sort-topics.js create mode 100644 views/mod/sort-topics.etlua diff --git a/apps/mod.lua b/apps/mod.lua index ecb33a4..01354c9 100644 --- a/apps/mod.lua +++ b/apps/mod.lua @@ -1,23 +1,46 @@ local app = require("lapis").Application() +local db = require("lapis.db") + local util = require("util") local models = require("models") local Users = models.Users -app:get("user_list", "/list", function(self) +-- everything here requires a logged in moderator +app:before_filter(function(self) self.me = util.get_logged_in_user(self) if not self.me then - return {redirect_to = self:url_for("all_topics")} + self:write{redirect_to = self:url_for("all_topics")} + return end - + if not self.me:is_mod() then - return {redirect_to = self:url_for("all_topics")} + self:write{redirect_to = self:url_for("all_topics")} + return end - +end) + +app:get("user_list", "/list", function(self) self.users = Users:select("") - + return {render = "mod.user-list"} end) +app:get("sort_topics", "/sort-topics", function(self) + self.topics = db.query("SELECT * FROM topics ORDER BY sort_order ASC") + self.page_title = "sorting topics" + return {render = "mod.sort-topics"} +end) + +app:post("sort_topics", "/sort-topics", function(self) + local updates = self.params + db.query("BEGIN") + for topic_id, new_order in pairs(updates) do + db.update("topics", {sort_order = new_order}, {id = topic_id}) + end + db.query("COMMIT") + return {redirect_to = self:url_for("sort_topics")} +end) + return app diff --git a/data/static/style.css b/data/static/style.css index d6d6f00..3c40604 100644 --- a/data/static/style.css +++ b/data/static/style.css @@ -364,3 +364,16 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus grid-area: topic-locked-container; border: 2px outset rgb(217.26, 220.38, 213.42); } + +.draggable-topic { + cursor: pointer; + user-select: none; + background-color: #c1ceb1; + padding: 20px; + margin: 12px 0; + border-top: 6px outset rgb(217.26, 220.38, 213.42); + border-bottom: 6px outset rgb(135.1928346457, 145.0974015748, 123.0025984252); +} +.draggable-topic.dragged { + background-color: rgb(177, 206, 204.5); +} diff --git a/js/sort-topics.js b/js/sort-topics.js new file mode 100644 index 0000000..e288266 --- /dev/null +++ b/js/sort-topics.js @@ -0,0 +1,45 @@ +// https://codepen.io/crouchingtigerhiddenadam/pen/qKXgap +let selected = null; +let container = document.getElementById("topics-container") + +function isBefore(el1, el2) { + let cur + if (el2.parentNode === el1.parentNode) { + for (cur = el1.previousSibling; cur; cur = cur.previousSibling) { + if (cur === el2) return true + } + } + return false; +} + +function dragOver(e) { + let target = e.target.closest(".draggable-topic") + + if (!target || target === selected) { + return; + } + + if (isBefore(selected, target)) { + container.insertBefore(selected, target) + } else { + container.insertBefore(selected, target.nextSibling) + } +} + +function dragEnd() { + if (!selected) return; + + selected.classList.remove("dragged") + selected = null; + for (let i = 0; i < container.childElementCount - 1; i++) { + let input = container.children[i].querySelector(".topic-input"); + input.value = i + 1; + } +} + +function dragStart(e) { + e.dataTransfer.effectAllowed = 'move' + e.dataTransfer.setData('text/plain', null) + selected = e.target + selected.classList.add("dragged") +} diff --git a/sass/style.scss b/sass/style.scss index 3f96f6d..aef0f0c 100644 --- a/sass/style.scss +++ b/sass/style.scss @@ -366,3 +366,18 @@ input[type="text"], input[type="password"], textarea, select { grid-area: topic-locked-container; border: 2px outset $light; } + + +.draggable-topic { + cursor: pointer; + user-select: none; + background-color: $accent_color; + padding: 20px; + margin: 12px 0; + border-top: 6px outset $light; + border-bottom: 6px outset $dark2; + + &.dragged { + background-color: $button_color; + } +} diff --git a/views/mod/sort-topics.etlua b/views/mod/sort-topics.etlua new file mode 100644 index 0000000..6fe4254 --- /dev/null +++ b/views/mod/sort-topics.etlua @@ -0,0 +1,19 @@ +
+ <% if infobox then %> + <% render("views.common.infobox", infobox) %> + <% end %> +

Change topics order

+

Drag topic titles to reoder them. Press submit when done. The topics will appear to users in the order set here.

+
+ <% for _, topic in ipairs(topics) do %> +
+
<%= topic.name %>
+
<%= topic.description %>
+ +
+ <% end %> + +
+
+ + diff --git a/views/topics/topics.etlua b/views/topics/topics.etlua index a323604..17fae1b 100644 --- a/views/topics/topics.etlua +++ b/views/topics/topics.etlua @@ -2,6 +2,7 @@

All topics

<% if me:is_mod() then %> ">Create new topic + ">Sort topics <% end %>