From 30721d53d623c365df430eb8fc40321af49c935a Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 15 May 2018 15:52:01 +0100 Subject: [PATCH] Implements posts and threads list in profile page. --- forum.nim | 77 ++++++++++++++++++++++++++++++------------ redesign/nimforum.scss | 14 +++++++- redesign/post.nim | 14 +++++++- redesign/profile.nim | 42 ++++++++++++++++++++--- 4 files changed, 119 insertions(+), 28 deletions(-) diff --git a/forum.nim b/forum.nim index 49c85bb..8cd3311 100644 --- a/forum.nim +++ b/forum.nim @@ -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" diff --git a/redesign/nimforum.scss b/redesign/nimforum.scss index dcab208..c617c52 100644 --- a/redesign/nimforum.scss +++ b/redesign/nimforum.scss @@ -499,4 +499,16 @@ hr { dd { margin-right: $control-padding-x-lg; } -} \ No newline at end of file +} + +.profile-post { + @extend .post; + + .profile-post-main { + flex: 1; + } + + .profile-post-time { + float: right; + } +} diff --git a/redesign/post.nim b/redesign/post.nim index 9ddbbb7..6a6f10d 100644 --- a/redesign/post.nim +++ b/redesign/post.nim @@ -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}") \ No newline at end of file + renderPostUrl(thread.id, post.id) + + proc renderPostUrl*(link: PostLink): string = + renderPostUrl(link.threadId, link.postId) \ No newline at end of file diff --git a/redesign/profile.nim b/redesign/profile.nim index 67cffee..91f3a96 100644 --- a/redesign/profile.nim +++ b/redesign/profile.nim @@ -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)