new user page

This commit is contained in:
Lera Elvoé 2025-06-05 11:02:59 +03:00
parent cfb676a453
commit 0c820183a6
Signed by: yagich
SSH Key Fingerprint: SHA256:6xjGb6uA7lAVcULa7byPEN//rQ0wPoG+UzYVMfZnbvc
4 changed files with 144 additions and 88 deletions

View File

@ -81,6 +81,23 @@ app:get("user", "/:username", function(self)
end end
end end
self.stats = db.query([[
SELECT
COUNT(posts.id) AS post_count,
COUNT(DISTINCT threads.id) AS thread_count,
MAX(threads.title) FILTER (WHERE threads.created_at = latest.created_at) AS latest_thread_title,
MAX(threads.slug) FILTER (WHERE threads.created_at = latest.created_at) AS latest_thread_slug
FROM users
LEFT JOIN posts ON posts.user_id = users.id
LEFT JOIN threads ON threads.user_id = users.id
LEFT JOIN (
SELECT user_id, MAX(created_at) AS created_at
FROM threads
GROUP BY user_id
) latest ON latest.user_id = users.id
WHERE users.id = ?
]], user.id)[1]
self.latest_posts = db.query([[ self.latest_posts = db.query([[
SELECT SELECT
posts.id, posts.created_at, post_history.content, post_history.edited_at, threads.title AS thread_title, topics.name as topic_name, threads.slug as thread_slug posts.id, posts.created_at, post_history.content, post_history.edited_at, threads.title AS thread_title, topics.name as topic_name, threads.slug as thread_slug

View File

@ -145,6 +145,10 @@ body {
overflow: hidden; overflow: hidden;
} }
.post-content.wider {
margin-right: 12.5%;
}
.post-inner { .post-inner {
height: 100%; height: 100%;
} }
@ -218,35 +222,43 @@ blockquote {
background-color: rgb(135.1928346457, 145.0974015748, 123.0025984252); background-color: rgb(135.1928346457, 145.0974015748, 123.0025984252);
} }
.user-posts { .user-info {
display: grid; display: grid;
grid-template-columns: 200px 1fr; grid-template-columns: 300px 1fr;
grid-template-rows: 1fr; grid-template-rows: 1fr;
gap: 0; gap: 0;
grid-auto-flow: row; grid-template-areas: "user-page-usercard user-page-stats";
grid-template-areas: "user-page-usercard user-posts-container";
border: 2px outset rgb(135.1928346457, 145.0974015748, 123.0025984252);
} }
.user-page-usercard { .user-page-usercard {
grid-area: user-page-usercard; grid-area: user-page-usercard;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 10px; padding: 20px 10px;
border: 4px outset rgb(217.26, 220.38, 213.42); border: 4px outset rgb(217.26, 220.38, 213.42);
background-color: rgb(143.7039271654, 144.3879625984, 142.8620374016); background-color: rgb(143.7039271654, 144.3879625984, 142.8620374016);
border-right: solid 2px; border-right: solid 2px;
} }
.user-posts-container { .user-page-stats {
grid-area: user-posts-container; grid-area: user-page-stats;
display: grid; padding: 20px 30px;
grid-template-columns: 1fr; border: 1px solid black;
grid-template-rows: 0.2fr 2.5fr; }
gap: 0px 0px;
grid-auto-flow: row; .user-stats-list {
grid-template-areas: "post-info" "post-content"; list-style: none;
margin: 0 0 10px 0;
}
.user-page-posts {
border-left: solid 1px black;
border-right: solid 1px black;
border-bottom: solid 1px black;
background-color: #c1ceb1;
}
.user-page-post-preview {
max-height: 200px;
mask-image: linear-gradient(180deg, #000 60%, transparent);
} }
.avatar { .avatar {

View File

@ -189,6 +189,10 @@ body {
overflow: hidden; overflow: hidden;
} }
.post-content.wider {
margin-right: 12.5%;
}
.post-inner { .post-inner {
height: 100%; height: 100%;
} }
@ -264,38 +268,44 @@ blockquote {
background-color: $dark2; background-color: $dark2;
} }
.user-posts { .user-info {
display: grid; display: grid;
grid-template-columns: 200px 1fr; grid-template-columns: 300px 1fr;
grid-template-rows: 1fr; grid-template-rows: 1fr;
gap: 0; gap: 0;
grid-auto-flow: row;
grid-template-areas: grid-template-areas:
"user-page-usercard user-posts-container"; "user-page-usercard user-page-stats";
border: 2px outset $dark2;
} }
.user-page-usercard { .user-page-usercard {
grid-area: user-page-usercard; grid-area: user-page-usercard;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 10px; padding: 20px 10px;
border: 4px outset $light; border: 4px outset $light;
background-color: $dark_bg; background-color: $dark_bg;
border-right: solid 2px; border-right: solid 2px;
} }
.user-posts-container { .user-page-stats {
grid-area: user-posts-container; grid-area: user-page-stats;
display: grid; padding: 20px 30px;
grid-template-columns: 1fr; border: 1px solid black;
grid-template-rows: 0.2fr 2.5fr; }
gap: 0px 0px;
grid-auto-flow: row; .user-stats-list {
grid-template-areas: list-style: none;
"post-info" margin: 0 0 10px 0;
"post-content"; }
.user-page-posts {
border-left: solid 1px black;
border-right: solid 1px black;
border-bottom: solid 1px black;
background-color: $accent_color;
}
.user-page-post-preview {
max-height: 200px;
mask-image: linear-gradient(180deg,#000 60%,transparent);
} }
.avatar { .avatar {

View File

@ -2,10 +2,7 @@
<% render("views.common.infobox", infobox) %> <% render("views.common.infobox", infobox) %>
<% end %> <% end %>
<div class="darkbg"> <div class="darkbg">
<h1 class="thread-title">Latest posts by <i><%= user.username %></i></h1> <h1 class="thread-title"><i><%= user.username %></i>'s profile</h1>
<div>
User permission: <i><%= PermissionLevelString[user.permission] %></i>
</div>
<% if user_is_me then -%> <% if user_is_me then -%>
<div class="user-actions"> <div class="user-actions">
<a class="linkbutton" href="<%= url_for("user_settings", {username = user.username}) %>">Settings</a> <a class="linkbutton" href="<%= url_for("user_settings", {username = user.username}) %>">Settings</a>
@ -13,61 +10,81 @@
<input class="warn" type="submit" value="Log out"> <input class="warn" type="submit" value="Log out">
</form> </form>
</div> </div>
<% if user:is_guest() then %>
<h2>You are a guest. A Moderator needs to approve your account before you will be able to post.</h2>
<% end %>
<% end %>
<% if me:is_mod() and not user:is_system() then %>
<h1 class="thread-title">Moderator controls</h1>
<% if user:is_guest() then %>
<p>This user is a guest. They signed up on <% render("views.common.timestamp", {timestamp = user.created_at}) -%>.</p>
<form class="modform" method="post" action="<%= url_for("confirm_user", {user_id = user.id}) %>">
<input type="submit" value="Confirm user">
</form>
<% else %> <% --[[ user is not guest ]] %>
<p>This user signed up on <% render("views.common.timestamp", {timestamp = user.created_at}) -%> and was confirmed on <% render("views.common.timestamp", {timestamp = user.confirmed_on}) %>.</p>
<% if user.permission < me.permission then %>
<form class="modform" method="post" action="<%= url_for("guest_user", {user_id = user.id}) %>">
<input class="warn" type="submit" value="Demote user to guest (soft ban)">
</form>
<% end %>
<% if me:is_admin() and not user:is_mod() then %>
<form class="modform" method="post" action="<%= url_for("mod_user", {user_id = user.id}) %>">
<input class="warn" type="submit" value="Promote user to moderator">
</form>
<% elseif user:is_mod() and user.permission < me.permission then %>
<form class="modform" method="post" action="<%= url_for("demod_user", {user_id = user.id}) %>">
<input class="critical" type="submit" value="Demote user to regular user">
</form>
<% end %>
<% end %>
<% end %> <% end %>
</div> </div>
<% --[[ duplicating code, maybe i'll refactor the post subview later to work anywhere <clown emoji>]] %>
<% for i, post in ipairs(latest_posts) do %> <div class="user-info">
<div class="user-posts"> <div class="user-page-usercard">
<div class="user-page-usercard"> <div class="usercard-inner">
<img class="avatar" src="<%= avatar_url(user) %>"> <img class="avatar" src="<%= avatar_url(user) %>">
<b class="big"><%= user.username %></b> <strong class="big"><%= user.username %></strong>
<em class="user-status"><%= user.status %></em> <% if user.status ~= "" then %>
</div> <em class="user-status"><%= user.status %></em>
<div class="user-posts-container"> <% end %>
<div class="post-info"> <% if user.signature_rendered ~= "" then %>
<div><a href="<%= url_for("thread", {slug = post.thread_slug}, {after = post.id}) .. "#post-" .. post.id %>" title="Permalink"><i> Signature:
<% if tonumber(post.edited_at) > tonumber(post.created_at) then -%> <div>
Edited in <%= post.thread_title %> at <% render("views.common.timestamp", {timestamp = post.edited_at}) -%> <%- user.signature_rendered %>
<% else -%> </div>
Posted in <%= post.thread_title %> on <% render("views.common.timestamp", {timestamp = post.created_at}) -%> <% end %>
<% end -%>
</i></a></div>
</div>
<div class="post-content">
<%- post.content %>
</div>
</div> </div>
</div> </div>
<% end %> <div class="user-page-stats">
<ul class="user-stats-list">
<% if user:is_guest() and user_is_me then %> <li>Permission: <%= PermissionLevelString[user.permission] %></li>
<h2>You are a guest. A Moderator needs to approve your account before you will be able to post.</h2> <li>Posts created: <%= stats.post_count %></li>
<% end %> <li>Threads started: <%= stats.thread_count %></li>
<% if stats.latest_thread_title then %>
<% if me:is_mod() and not user:is_system() then %> <li>Latest started thread: <a href="<%= url_for("thread", {slug = stats.latest_thread_slug}) %>"><%= stats.latest_thread_title %></a></li>
<div class="darkbg">
<h1>Moderator controls</h2>
<% if user:is_guest() then %>
<p>This user is a guest. They signed up on <% render("views.common.timestamp", {timestamp = user.created_at}) -%>.</p>
<form class="modform" method="post" action="<%= url_for("confirm_user", {user_id = user.id}) %>">
<input type="submit" value="Confirm user">
</form>
<% else %> <% --[[ user is not guest ]] %>
<p>This user signed up on <% render("views.common.timestamp", {timestamp = user.created_at}) -%> and was confirmed on <% render("views.common.timestamp", {timestamp = user.confirmed_on}) %>.</p>
<% if user.permission < me.permission then %>
<form class="modform" method="post" action="<%= url_for("guest_user", {user_id = user.id}) %>">
<input class="warn" type="submit" value="Demote user to guest (soft ban)">
</form>
<% end %> <% end %>
<% if me:is_admin() and not user:is_mod() then %> </ul>
<form class="modform" method="post" action="<%= url_for("mod_user", {user_id = user.id}) %>"> Latest posts:
<input class="warn" type="submit" value="Promote user to moderator"> <div class="user-page-posts">
</form> <% for _, post in ipairs(latest_posts) do %>
<% elseif user:is_mod() and user.permission < me.permission then %> <div class="post-content-container">
<form class="modform" method="post" action="<%= url_for("demod_user", {user_id = user.id}) %>"> <div class="post-info">
<input class="critical" type="submit" value="Demote user to regular user"> <% local post_url = get_post_url(post.id) %>
</form> <a href="<%= post_url %>" title="Permalink"><i>
<% if tonumber(post.edited_at) > tonumber(post.created_at) then -%>
Edited at <% render("views.common.timestamp", {timestamp = post.edited_at}) -%> in <%= post.thread_title %>
<% else -%>
Posted on <% render("views.common.timestamp", {timestamp = post.created_at}) -%> in <%= post.thread_title %>
<% end -%>
</i></a>
</div>
<div class="post-content wider user-page-post-preview">
<div class="post-inner"><%- post.content %></div>
</div>
</div>
<% end %> <% end %>
<% end %> </div>
</div> </div>
<% end %> </div>