use infobox to signal topic locked
This commit is contained in:
		
							
								
								
									
										3
									
								
								app.lua
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								app.lua
									
									
									
									
									
								
							@@ -21,6 +21,9 @@ local function inject_methods(req)
 | 
				
			|||||||
    return util.ntob(v)
 | 
					    return util.ntob(v)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
  req.PermissionLevelString = constants.PermissionLevelString
 | 
					  req.PermissionLevelString = constants.PermissionLevelString
 | 
				
			||||||
 | 
					  req.infobox_message = function (_, s)
 | 
				
			||||||
 | 
					    return util.infobox_message(s)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  util.pop_infobox(req)
 | 
					  util.pop_infobox(req)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,9 @@ app:post("thread_create", "/create", function(self)
 | 
				
			|||||||
  if not topic then
 | 
					  if not topic then
 | 
				
			||||||
    return {redirect_to = self:url_for("topics")}
 | 
					    return {redirect_to = self:url_for("topics")}
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					  if util.is_topic_locked(topic) then
 | 
				
			||||||
 | 
					    return {redirect_to = self:url_for("topics")}
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local title = lapis_util.trim(self.params.title)
 | 
					  local title = lapis_util.trim(self.params.title)
 | 
				
			||||||
  local time = os.time()
 | 
					  local time = os.time()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										164
									
								
								util.lua
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								util.lua
									
									
									
									
									
								
							@@ -3,6 +3,7 @@ local magick = require("magick")
 | 
				
			|||||||
local db = require("lapis.db")
 | 
					local db = require("lapis.db")
 | 
				
			||||||
local html_escape = require("lapis.html").escape
 | 
					local html_escape = require("lapis.html").escape
 | 
				
			||||||
local constants   = require("constants")
 | 
					local constants   = require("constants")
 | 
				
			||||||
 | 
					local string_trim = require("lapis.util").trim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local Avatars = require("models").Avatars
 | 
					local Avatars = require("models").Avatars
 | 
				
			||||||
local Users = require("models").Users
 | 
					local Users = require("models").Users
 | 
				
			||||||
@@ -33,10 +34,131 @@ util.TransientUser = {
 | 
				
			|||||||
  username = "Deleted User",
 | 
					  username = "Deleted User",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- PURE API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function util.get_user_avatar_url(req, user)
 | 
					function util.get_user_avatar_url(req, user)
 | 
				
			||||||
  return Avatars:find(user.avatar_id).file_path
 | 
					  return Avatars:find(user.avatar_id).file_path
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---split a string
 | 
				
			||||||
 | 
					---@param s string subject
 | 
				
			||||||
 | 
					---@param delimiter string? string to split by, can be empty to split by character
 | 
				
			||||||
 | 
					---@param max_matches integer? the maximum number of returned elements
 | 
				
			||||||
 | 
					---@param trim boolean? whether to trim whitespace off matches
 | 
				
			||||||
 | 
					---@param allow_empty boolean? should empty matches be in the resulting table
 | 
				
			||||||
 | 
					---@return string[]
 | 
				
			||||||
 | 
					function util.s_split(s, delimiter, max_matches, trim, allow_empty)
 | 
				
			||||||
 | 
					  local result = {}
 | 
				
			||||||
 | 
					  if s == "" then
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  trim = trim == nil and true or trim
 | 
				
			||||||
 | 
					  local tr = function(subj)
 | 
				
			||||||
 | 
					    if trim then return string_trim(subj) else return subj end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  max_matches = max_matches or -1
 | 
				
			||||||
 | 
					  allow_empty = allow_empty == nil and true or allow_empty
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if delimiter == "" then
 | 
				
			||||||
 | 
					    for i=1, #s do
 | 
				
			||||||
 | 
					      local c = s:sub(i, 1)
 | 
				
			||||||
 | 
					      if allow_empty or c ~= "" then
 | 
				
			||||||
 | 
					        table.insert(result, c)
 | 
				
			||||||
 | 
					        if max_matches > 0 and #result == max_matches then
 | 
				
			||||||
 | 
					          break
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  local current_pos = 1
 | 
				
			||||||
 | 
					  local delim_len = #delimiter
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  while true do
 | 
				
			||||||
 | 
					    if max_matches > 0 and #result >= max_matches then
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					---@diagnostic disable-next-line: param-type-mismatch
 | 
				
			||||||
 | 
					    local start_pos, end_pos = s:find(delimiter, current_pos, true)
 | 
				
			||||||
 | 
					    if not start_pos then
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    local substr = s:sub(current_pos, start_pos - 1)
 | 
				
			||||||
 | 
					    if allow_empty or substr ~= "" then
 | 
				
			||||||
 | 
					      table.insert(result, tr(substr))
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    current_pos = end_pos + 1
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  local substr = s:sub(current_pos)
 | 
				
			||||||
 | 
					  if allow_empty or substr ~= "" then
 | 
				
			||||||
 | 
					    table.insert(result, tr(substr))
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return result
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.split_sentences(sentences, max_sentences)
 | 
				
			||||||
 | 
					  return util.s_split(sentences, ".", max_sentences or 2, true, false)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.infobox_message(msg)
 | 
				
			||||||
 | 
					  local sentences = util.split_sentences(msg)
 | 
				
			||||||
 | 
					  if #sentences == 1 then
 | 
				
			||||||
 | 
					    return "<b>" .. sentences[1] .. ". " .. "</b>"
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  return "<span><b>" .. sentences[1] .. ". " .. "</b> " .. sentences[2] .. ".</span>"
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.get_logged_in_user(req)
 | 
				
			||||||
 | 
					  if req.session.session_key == nil then
 | 
				
			||||||
 | 
					    return nil
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local session = db.select('* FROM "sessions" WHERE "key" = ? AND "expires_at" > "?" LIMIT 1', req.session.session_key, os.time())
 | 
				
			||||||
 | 
					  if #session > 0 then
 | 
				
			||||||
 | 
					    return Users:find({id = session[1].user_id})
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return nil
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.get_logged_in_user_or_transient(req)
 | 
				
			||||||
 | 
					  return util.get_logged_in_user(req) or util.TransientUser
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.ntob(v)
 | 
				
			||||||
 | 
					  return v ~= 0
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.bton(b)
 | 
				
			||||||
 | 
					  return 1 and b or 0
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function util.stob(s)
 | 
				
			||||||
 | 
					  if s == "true" then
 | 
				
			||||||
 | 
					    return true
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  if s == "false" then
 | 
				
			||||||
 | 
					    return false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.is_topic_locked(topic)
 | 
				
			||||||
 | 
					  return util.ntob(topic.is_locked)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- OTHER API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function util.validate_and_create_image(input_image, filename)
 | 
					function util.validate_and_create_image(input_image, filename)
 | 
				
			||||||
  local img = magick.load_image_from_blob(input_image)
 | 
					  local img = magick.load_image_from_blob(input_image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,48 +214,6 @@ function util.destroy_avatar(avatar_id)
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function util.get_logged_in_user(req)
 | 
					 | 
				
			||||||
  if req.session.session_key == nil then
 | 
					 | 
				
			||||||
    return nil
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  local session = db.select('* FROM "sessions" WHERE "key" = ? AND "expires_at" > "?" LIMIT 1', req.session.session_key, os.time())
 | 
					 | 
				
			||||||
  if #session > 0 then
 | 
					 | 
				
			||||||
    return Users:find({id = session[1].user_id})
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return nil
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function util.get_logged_in_user_or_transient(req)
 | 
					 | 
				
			||||||
  return util.get_logged_in_user(req) or util.TransientUser
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function util.ntob(v)
 | 
					 | 
				
			||||||
  return v ~= 0
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function util.bton(b)
 | 
					 | 
				
			||||||
  return 1 and b or 0
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function util.stob(s)
 | 
					 | 
				
			||||||
  if s == "true" then
 | 
					 | 
				
			||||||
    return true
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
  if s == "false" then
 | 
					 | 
				
			||||||
    return false
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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)
 | 
					function util.create_post(thread_id, user_id, content)
 | 
				
			||||||
  db.query("BEGIN")
 | 
					  db.query("BEGIN")
 | 
				
			||||||
  local post = Posts:create({
 | 
					  local post = Posts:create({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
<%
 | 
					<%
 | 
				
			||||||
  local class = "infobox " .. constants.InfoboxHTMLClass[kind]
 | 
					  local class = "infobox " .. constants.InfoboxHTMLClass[kind]
 | 
				
			||||||
  local icon = constants.InfoboxIcons[kind]
 | 
					  local icon = constants.InfoboxIcons[kind]
 | 
				
			||||||
 | 
					  local sentences = infobox_message(msg)
 | 
				
			||||||
%>
 | 
					%>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="<%= class %>">
 | 
					<div class="<%= class %>">
 | 
				
			||||||
@@ -8,6 +9,6 @@
 | 
				
			|||||||
  <div class="infobox-icon-container">
 | 
					  <div class="infobox-icon-container">
 | 
				
			||||||
  <% render(icon) %>
 | 
					  <% render(icon) %>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
    <%= msg %>
 | 
					    <%- sentences %>
 | 
				
			||||||
  </span>
 | 
					  </span>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@
 | 
				
			|||||||
  <% render("views.common.infobox", infobox) %>
 | 
					  <% render("views.common.infobox", infobox) %>
 | 
				
			||||||
<% end %>
 | 
					<% end %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<% local is_locked = ntob(topic.is_locked) %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<nav class="darkbg">
 | 
					<nav class="darkbg">
 | 
				
			||||||
  <h1 class="thread-title">All threads in "<%= topic.name %>"</h1>
 | 
					  <h1 class="thread-title">All threads in "<%= topic.name %>"</h1>
 | 
				
			||||||
  <span><%= topic.description %></span>
 | 
					  <span><%= topic.description %></span>
 | 
				
			||||||
@@ -12,25 +14,27 @@
 | 
				
			|||||||
    <p>Your account is still pending confirmation by a moderator. You are not able to create a new thread or post at this time.</p>
 | 
					    <p>Your account is still pending confirmation by a moderator. You are not able to create a new thread or post at this time.</p>
 | 
				
			||||||
  <% elseif thread_create_error == ThreadCreateError.LOGGED_OUT then %>
 | 
					  <% elseif thread_create_error == ThreadCreateError.LOGGED_OUT then %>
 | 
				
			||||||
    <p>Only logged in users can create threads. <a href="<%= url_for("user_signup") %>">Sign up</a> or <a href="<%= url_for("user_login")%>">log in</a> to create a thread.</p>
 | 
					    <p>Only logged in users can create threads. <a href="<%= url_for("user_signup") %>">Sign up</a> or <a href="<%= url_for("user_login")%>">log in</a> to create a thread.</p>
 | 
				
			||||||
  <% else %>
 | 
					 | 
				
			||||||
    <p>This topic is locked.</p>
 | 
					 | 
				
			||||||
  <% end %>
 | 
					  <% end %>
 | 
				
			||||||
  <% if me:is_mod() then %>
 | 
					  <% if me:is_mod() then %>
 | 
				
			||||||
    <a class="linkbutton" href="<%= url_for("topic_edit", {slug = topic.slug}) %>">Edit topic</a>
 | 
					    <a class="linkbutton" href="<%= url_for("topic_edit", {slug = topic.slug}) %>">Edit topic</a>
 | 
				
			||||||
    <form class="modform" method="post" action="<%= url_for("topic_edit", {slug = topic.slug}) %>">
 | 
					    <form class="modform" method="post" action="<%= url_for("topic_edit", {slug = topic.slug}) %>">
 | 
				
			||||||
      <input type="hidden" name="is_locked" value="<%= not ntob(topic.is_locked) %>">
 | 
					      <input type="hidden" name="is_locked" value="<%= not is_locked %>">
 | 
				
			||||||
      <input class="warn" type="submit" id="lock" value="<%= ntob(topic.is_locked) and "Unlock topic" or "Lock topic" %>">
 | 
					      <input class="warn" type="submit" id="lock" value="<%= is_locked and "Unlock topic" or "Lock topic" %>">
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
  <% end %>
 | 
					  <% end %>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<% if is_locked then -%>
 | 
				
			||||||
 | 
					  <% render("views.common.infobox", {kind = constants.InfoboxKind.LOCK, msg = "This topic is locked. Only moderators can create new threads."}) %>
 | 
				
			||||||
 | 
					<% end -%>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<% if #threads_list == 0 then %>
 | 
					<% if #threads_list == 0 then %>
 | 
				
			||||||
  <p>There are no threads in this topic.</p>
 | 
					  <p>There are no threads in this topic.</p>
 | 
				
			||||||
<% else %>
 | 
					<% else %>
 | 
				
			||||||
  <% for _, thread in ipairs(threads_list) do %>
 | 
					  <% for _, thread in ipairs(threads_list) do %>
 | 
				
			||||||
    <% local is_stickied = ntob(thread.is_stickied) %>
 | 
					    <% local is_stickied = ntob(thread.is_stickied) %>
 | 
				
			||||||
    <% local is_locked = ntob(thread.is_locked) %>
 | 
					    <% local thread_is_locked = ntob(thread.is_locked) %>
 | 
				
			||||||
    <div class="thread">
 | 
					    <div class="thread">
 | 
				
			||||||
      <div class="thread-sticky-container contain-svg">
 | 
					      <div class="thread-sticky-container contain-svg">
 | 
				
			||||||
        <% if is_stickied then -%>
 | 
					        <% if is_stickied then -%>
 | 
				
			||||||
@@ -54,7 +58,7 @@
 | 
				
			|||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="thread-locked-container contain-svg">
 | 
					      <div class="thread-locked-container contain-svg">
 | 
				
			||||||
        <% if is_locked then -%>
 | 
					        <% if thread_is_locked then -%>
 | 
				
			||||||
          <% render("svg-icons.lock") %>
 | 
					          <% render("svg-icons.lock") %>
 | 
				
			||||||
          <i>Locked</i>
 | 
					          <i>Locked</i>
 | 
				
			||||||
        <% end -%>
 | 
					        <% end -%>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@
 | 
				
			|||||||
    <% local is_locked = ntob(topic.is_locked) %>
 | 
					    <% local is_locked = ntob(topic.is_locked) %>
 | 
				
			||||||
    <div class="topic">
 | 
					    <div class="topic">
 | 
				
			||||||
      <div class="topic-info-container">
 | 
					      <div class="topic-info-container">
 | 
				
			||||||
        <a href=<%= url_for("topic", {slug = topic.slug}) %>><%= topic.name %></a>
 | 
					        <a class="thread-title" href=<%= url_for("topic", {slug = topic.slug}) %>><%= topic.name %></a>
 | 
				
			||||||
        <%= topic.description %>
 | 
					        <%= topic.description %>
 | 
				
			||||||
        <% if topic.latest_thread_username then %>
 | 
					        <% if topic.latest_thread_username then %>
 | 
				
			||||||
        <span>
 | 
					        <span>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user