Implements posts and threads list in profile page.
This commit is contained in:
parent
2dd9dd52a2
commit
30721d53d6
4 changed files with 119 additions and 28 deletions
77
forum.nim
77
forum.nim
|
|
@ -1214,14 +1214,33 @@ routes:
|
||||||
var
|
var
|
||||||
username = @"username"
|
username = @"username"
|
||||||
|
|
||||||
|
# Have to do this because SQLITE doesn't support `in` queries with
|
||||||
|
# multiple columns :/
|
||||||
|
# TODO: Figure out a better way. This is horrible.
|
||||||
|
let creatorSubquery = """
|
||||||
|
(select $1 from post p
|
||||||
|
where p.thread = t.id
|
||||||
|
order by p.id asc limit 1)
|
||||||
|
"""
|
||||||
|
|
||||||
|
let threadsFrom = """
|
||||||
|
from thread t, post p
|
||||||
|
where ? in $1 and p.id in $2
|
||||||
|
""" % [creatorSubquery % "author", creatorSubquery % "id"]
|
||||||
|
|
||||||
|
let postsFrom = """
|
||||||
|
from post p, person u, thread t
|
||||||
|
where u.id = p.author and p.thread = t.id and u.name = ?
|
||||||
|
"""
|
||||||
|
|
||||||
let postsQuery = sql("""
|
let postsQuery = sql("""
|
||||||
select p.id, p.content, strftime('%s', p.creation), p.author,
|
select p.id, strftime('%s', p.creation),
|
||||||
u.name, u.email, strftime('%s', u.lastOnline), u.status,
|
u.name, u.email, strftime('%s', u.lastOnline), u.status,
|
||||||
strftime('%s', u.creation)
|
strftime('%s', u.creation), u.id,
|
||||||
from post p, person u
|
t.name, t.id
|
||||||
where u.id = p.author and u.name = ?
|
$1
|
||||||
order by p.id desc;
|
order by p.id desc limit 10;
|
||||||
""")
|
""" % postsFrom)
|
||||||
|
|
||||||
var profile = Profile(
|
var profile = Profile(
|
||||||
threads: @[],
|
threads: @[],
|
||||||
|
|
@ -1229,29 +1248,43 @@ routes:
|
||||||
)
|
)
|
||||||
|
|
||||||
let rows = db.getAllRows(postsQuery, username)
|
let rows = db.getAllRows(postsQuery, username)
|
||||||
|
let userID = rows[0][7]
|
||||||
profile.user = selectUser(@[
|
profile.user = selectUser(@[
|
||||||
rows[0][4], rows[0][5], rows[0][6], rows[0][7]
|
rows[0][2], rows[0][3], rows[0][4], rows[0][5]
|
||||||
], avatarSize=200)
|
], avatarSize=200)
|
||||||
profile.joinTime = rows[0][8].parseInt()
|
profile.joinTime = rows[0][7].parseInt()
|
||||||
|
profile.postCount =
|
||||||
|
getValue(db, sql("select count(*) " & postsFrom), username).parseInt()
|
||||||
|
profile.threadCount =
|
||||||
|
getValue(db, sql("select count(*) " & threadsFrom), userID).parseInt()
|
||||||
|
|
||||||
if c.rank >= Admin:
|
if c.rank >= Admin:
|
||||||
profile.email = some(rows[0][5])
|
profile.email = some(rows[0][3])
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
let firstPostForThread = getRow(db,
|
|
||||||
sql"""select t.id, t.name, t.views, t.modified, p.id
|
|
||||||
from thread t, post p
|
|
||||||
where p.thread = t.id
|
|
||||||
order by p.id limit 1""", row[0])
|
|
||||||
|
|
||||||
# Check if the thread that contains this post was created by the user.
|
|
||||||
if firstPostForThread[4] == row[0]:
|
|
||||||
profile.threads.add(
|
|
||||||
selectThread(firstPostForThread)
|
|
||||||
)
|
|
||||||
|
|
||||||
profile.posts.add(
|
profile.posts.add(
|
||||||
selectPost(row, @[])
|
PostLink(
|
||||||
|
creation: row[1].parseInt(),
|
||||||
|
topic: row[8],
|
||||||
|
threadId: row[9].parseInt(),
|
||||||
|
postId: row[0].parseInt()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let threadsQuery = sql("""
|
||||||
|
select t.id, t.name, strftime('%s', p.creation), p.id
|
||||||
|
$1
|
||||||
|
order by t.id desc
|
||||||
|
limit 10;
|
||||||
|
""" % threadsFrom)
|
||||||
|
for row in db.getAllRows(threadsQuery, userID):
|
||||||
|
profile.threads.add(
|
||||||
|
PostLink(
|
||||||
|
creation: row[2].parseInt(),
|
||||||
|
topic: row[1],
|
||||||
|
threadId: row[0].parseInt(),
|
||||||
|
postId: row[3].parseInt()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
resp $(%profile), "application/json"
|
resp $(%profile), "application/json"
|
||||||
|
|
|
||||||
|
|
@ -500,3 +500,15 @@ hr {
|
||||||
margin-right: $control-padding-x-lg;
|
margin-right: $control-padding-x-lg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.profile-post {
|
||||||
|
@extend .post;
|
||||||
|
|
||||||
|
.profile-post-main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-post-time {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,19 @@ type
|
||||||
info*: PostInfo
|
info*: PostInfo
|
||||||
moreBefore*: seq[int]
|
moreBefore*: seq[int]
|
||||||
|
|
||||||
|
PostLink* = object ## Used by profile
|
||||||
|
creation*: int64
|
||||||
|
topic*: string
|
||||||
|
threadId*: int
|
||||||
|
postId*: int
|
||||||
|
|
||||||
when defined(js):
|
when defined(js):
|
||||||
import karaxutils
|
import karaxutils
|
||||||
|
proc renderPostUrl*(threadId, postId: int): string =
|
||||||
|
makeUri(fmt"/t/{threadId}#{postId}")
|
||||||
|
|
||||||
proc renderPostUrl*(post: Post, thread: Thread): string =
|
proc renderPostUrl*(post: Post, thread: Thread): string =
|
||||||
makeUri(fmt"/t/{thread.id}#{post.id}")
|
renderPostUrl(thread.id, post.id)
|
||||||
|
|
||||||
|
proc renderPostUrl*(link: PostLink): string =
|
||||||
|
renderPostUrl(link.threadId, link.postId)
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import options, httpcore, json, sugar
|
import options, httpcore, json, sugar, times
|
||||||
|
|
||||||
import threadlist, post, category, error
|
import threadlist, post, category, error
|
||||||
type
|
type
|
||||||
Profile* = object
|
Profile* = object
|
||||||
user*: User
|
user*: User
|
||||||
joinTime*: int64
|
joinTime*: int64
|
||||||
threads*: seq[Thread]
|
threads*: seq[PostLink]
|
||||||
posts*: seq[Post]
|
posts*: seq[PostLink]
|
||||||
|
postCount*: int
|
||||||
|
threadCount*: int
|
||||||
# Information that only admins should see.
|
# Information that only admins should see.
|
||||||
email*: Option[string]
|
email*: Option[string]
|
||||||
|
|
||||||
|
|
@ -38,6 +40,20 @@ when defined(js):
|
||||||
|
|
||||||
state.profile = some(profile)
|
state.profile = some(profile)
|
||||||
|
|
||||||
|
proc genPostLink(link: PostLink): VNode =
|
||||||
|
let url = renderPostUrl(link)
|
||||||
|
result = buildHtml():
|
||||||
|
tdiv(class="profile-post"):
|
||||||
|
tdiv(class="profile-post-main"):
|
||||||
|
tdiv(class="profile-post-title"):
|
||||||
|
a(href=url):
|
||||||
|
text link.topic
|
||||||
|
tdiv(class="profile-post-time"):
|
||||||
|
let title = link.creation.fromUnix().local.
|
||||||
|
format("MMM d, yyyy HH:mm")
|
||||||
|
p(title=title):
|
||||||
|
text renderActivity(link.creation)
|
||||||
|
|
||||||
proc render*(state: ProfileState, username: string): VNode =
|
proc render*(state: ProfileState, username: string): VNode =
|
||||||
if state.status != Http200:
|
if state.status != Http200:
|
||||||
return renderError("Couldn't retrieve profile.")
|
return renderError("Couldn't retrieve profile.")
|
||||||
|
|
@ -63,16 +79,34 @@ when defined(js):
|
||||||
dt(text "Joined")
|
dt(text "Joined")
|
||||||
dd(text threadlist.renderActivity(profile.joinTime))
|
dd(text threadlist.renderActivity(profile.joinTime))
|
||||||
dt(text "Last Post")
|
dt(text "Last Post")
|
||||||
dd(text renderActivity(profile.posts[0].info.creation))
|
dd(text renderActivity(profile.posts[0].creation))
|
||||||
dt(text "Last Online")
|
dt(text "Last Online")
|
||||||
dd(text renderActivity(profile.user.lastOnline))
|
dd(text renderActivity(profile.user.lastOnline))
|
||||||
|
dt(text "Posts")
|
||||||
|
dd():
|
||||||
|
if profile.postCount > 999:
|
||||||
|
text $(profile.postCount / 1000) & "k"
|
||||||
|
else:
|
||||||
|
text $profile.postCount
|
||||||
|
dt(text "Threads")
|
||||||
|
dd():
|
||||||
|
if profile.threadCount > 999:
|
||||||
|
text $(profile.threadCount / 1000) & "k"
|
||||||
|
else:
|
||||||
|
text $profile.threadCount
|
||||||
dt(text "Rank")
|
dt(text "Rank")
|
||||||
dd(text $profile.user.rank)
|
dd(text $profile.user.rank)
|
||||||
|
|
||||||
tdiv(class="columns"):
|
tdiv(class="columns"):
|
||||||
tdiv(class="column col-6"):
|
tdiv(class="column col-6"):
|
||||||
h4(text "Latest Posts")
|
h4(text "Latest Posts")
|
||||||
|
tdiv(class="posts"):
|
||||||
|
for post in profile.posts:
|
||||||
|
genPostLink(post)
|
||||||
tdiv(class="column col-6"):
|
tdiv(class="column col-6"):
|
||||||
h4(text "Latest Threads")
|
h4(text "Latest Threads")
|
||||||
|
tdiv(class="posts"):
|
||||||
|
for thread in profile.threads:
|
||||||
|
genPostLink(thread)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue