Implements posts and threads list in profile page.

This commit is contained in:
Dominik Picheta 2018-05-15 15:52:01 +01:00
commit 30721d53d6
4 changed files with 119 additions and 28 deletions

View file

@ -1214,14 +1214,33 @@ routes:
var
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("""
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,
strftime('%s', u.creation)
from post p, person u
where u.id = p.author and u.name = ?
order by p.id desc;
""")
strftime('%s', u.creation), u.id,
t.name, t.id
$1
order by p.id desc limit 10;
""" % postsFrom)
var profile = Profile(
threads: @[],
@ -1229,29 +1248,43 @@ routes:
)
let rows = db.getAllRows(postsQuery, username)
let userID = rows[0][7]
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)
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:
profile.email = some(rows[0][5])
profile.email = some(rows[0][3])
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(
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"

View file

@ -499,4 +499,16 @@ hr {
dd {
margin-right: $control-padding-x-lg;
}
}
}
.profile-post {
@extend .post;
.profile-post-main {
flex: 1;
}
.profile-post-time {
float: right;
}
}

View file

@ -21,7 +21,19 @@ type
info*: PostInfo
moreBefore*: seq[int]
PostLink* = object ## Used by profile
creation*: int64
topic*: string
threadId*: int
postId*: int
when defined(js):
import karaxutils
proc renderPostUrl*(threadId, postId: int): string =
makeUri(fmt"/t/{threadId}#{postId}")
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)

View file

@ -1,12 +1,14 @@
import options, httpcore, json, sugar
import options, httpcore, json, sugar, times
import threadlist, post, category, error
type
Profile* = object
user*: User
joinTime*: int64
threads*: seq[Thread]
posts*: seq[Post]
threads*: seq[PostLink]
posts*: seq[PostLink]
postCount*: int
threadCount*: int
# Information that only admins should see.
email*: Option[string]
@ -38,6 +40,20 @@ when defined(js):
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 =
if state.status != Http200:
return renderError("Couldn't retrieve profile.")
@ -63,16 +79,34 @@ when defined(js):
dt(text "Joined")
dd(text threadlist.renderActivity(profile.joinTime))
dt(text "Last Post")
dd(text renderActivity(profile.posts[0].info.creation))
dd(text renderActivity(profile.posts[0].creation))
dt(text "Last Online")
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")
dd(text $profile.user.rank)
tdiv(class="columns"):
tdiv(class="column col-6"):
h4(text "Latest Posts")
tdiv(class="posts"):
for post in profile.posts:
genPostLink(post)
tdiv(class="column col-6"):
h4(text "Latest Threads")
tdiv(class="posts"):
for thread in profile.threads:
genPostLink(thread)