From 8b01e452b602d0d9ff8f1543e72d1a795ae71276 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 13 May 2018 22:59:29 +0100 Subject: [PATCH] Improves post rendering to support multiple load more buttons. --- forum.nim | 83 ++++++++++++++++++++++++------------ redesign/post.nim | 4 +- redesign/postlist.nim | 99 +++++++++++++++++++++++++------------------ 3 files changed, 116 insertions(+), 70 deletions(-) diff --git a/forum.nim b/forum.nim index b7998e7..9321e0f 100644 --- a/forum.nim +++ b/forum.nim @@ -9,7 +9,7 @@ import os, strutils, times, md5, strtabs, math, db_sqlite, scgi, jester, asyncdispatch, asyncnet, cache, sequtils, - parseutils, utils, random, rst, ranks, recaptcha, json, re + parseutils, utils, random, rst, ranks, recaptcha, json, re, sugar import cgi except setCookie import options @@ -1026,6 +1026,20 @@ proc selectUser(userRow: seq[string]): threadlist.User = isOnline: isOnline ) +proc selectPost(postRow: seq[string], skippedPosts: seq[int]): Post = + return Post( + id: postRow[0].parseInt, + author: selectUser(@[postRow[4], postRow[5], postRow[6]]), + likes: @[], # TODO: + seen: false, # TODO: + history: @[], # TODO: + info: PostInfo( + creation: postRow[2].parseInt, + content: postRow[1].rstToHtml() + ), + moreBefore: skippedPosts + ) + proc selectThread(threadRow: seq[string]): Thread = const postsQuery = sql"""select count(*), strftime('%s', creation) from post @@ -1101,9 +1115,10 @@ routes: createTFD() var id = getInt(@"id", -1) - start = getInt(@"start", 0) - count = getInt(@"count", 5) + anchor = getInt(@"anchor", -1) cond id != -1 + const + count = 10 const threadsQuery = sql"""select id, name, views, strftime('%s', modified) from thread @@ -1124,34 +1139,50 @@ routes: from post p, person u where u.id = p.author and p.thread = ? and $# and (u.status <> 'Spammer' or p.author = ?) - order by p.id limit ?, ?""" % modClause + order by p.id""" % modClause ) - let pstCount = getValue( - db, - sql"select count(*) from post where thread = ?;", - id - ).parseInt() - let moreCount = max(0, pstCount - (start + count)) - var list = PostList( posts: @[], history: @[], - thread: thread, - moreCount: moreCount) - for post in getAllRows(db, postsQuery, id, c.userId, c.userId, - start, count): - list.posts.add(Post( - id: post[0].parseInt, - author: selectUser(@[post[4], post[5], post[6]]), - likes: @[], # TODO: - seen: false, # TODO: - history: @[], # TODO: - info: PostInfo( - creation: post[2].parseInt, - content: post[1].rstToHtml() - ) - )) + thread: thread + ) + let rows = getAllRows(db, postsQuery, id, c.userId, c.userId) + + var skippedPosts: seq[int] = @[] + for i in 0 ..< rows.len: + let id = rows[i][0].parseInt + + let addDetail = i < count or rows.len-i < count or id == anchor + + if addDetail: + let post = selectPost(rows[i], skippedPosts) + list.posts.add(post) + skippedPosts = @[] + else: + skippedPosts.add(id) + + resp $(%list), "application/json" + + get "/karax/specific_posts.json": + createTFD() + var + ids = parseJson(@"ids") + + cond ids.kind == JArray + let intIDs = ids.elems.map(x => x.getInt()) + let postsQuery = sql(""" + select p.id, p.content, strftime('%s', p.creation), p.author, + u.name, u.email, strftime('%s', u.lastOnline) + from post p, person u + where u.id = p.author and p.id in ($#) + order by p.id; + """ % intIDs.join(",")) # TODO: It's horrible that I have to do this. + + var list: seq[Post] = @[] + + for row in db.getAllRows(postsQuery): + list.add(selectPost(row, @[])) resp $(%list), "application/json" diff --git a/redesign/post.nim b/redesign/post.nim index 616fa1d..9ddbbb7 100644 --- a/redesign/post.nim +++ b/redesign/post.nim @@ -8,7 +8,7 @@ type creation*: int64 content*: string - Post* = object + Post* = ref object id*: int author*: User likes*: seq[User] ## Users that liked this post. @@ -19,7 +19,7 @@ type history*: seq[PostInfo] ## If the post was edited this will contain the ## older versions of the post. info*: PostInfo - + moreBefore*: seq[int] when defined(js): import karaxutils diff --git a/redesign/postlist.nim b/redesign/postlist.nim index 8ffc423..c585e64 100644 --- a/redesign/postlist.nim +++ b/redesign/postlist.nim @@ -10,7 +10,6 @@ type ## older versions of the thread (title/category ## changes). posts*: seq[Post] - moreCount*: int when defined(js): include karax/prelude @@ -38,7 +37,7 @@ when defined(js): var state = newState() - proc onPostList(httpStatus: int, response: kstring, start: int) = + proc onPostList(httpStatus: int, response: kstring) = state.loading = false state.status = httpStatus.HttpCode if state.status != Http200: return @@ -46,20 +45,62 @@ when defined(js): let parsed = parseJson($response) let list = to(parsed, PostList) - if state.list.isSome and state.list.get().thread.id == list.thread.id: - var old = state.list.get() - for i in 0.. onMorePosts(s, r, start, post) + ) + + proc genLoadMore(post: Post, start: int): VNode = + result = buildHtml(): + tdiv(class="information load-more-posts", + onClick=(e: Event, n: VNode) => onLoadMore(e, n, start, post)): + tdiv(class="information-icon"): + italic(class="fas fa-comment-dots") + tdiv(class="information-main"): + if state.loading: + tdiv(class="loading loading-lg") + else: + tdiv(class="information-title"): + text "Load more posts " + span(class="more-post-count"): + text "(" & $post.moreBefore.len & ")" + proc genPost(post: Post, thread: Thread, isLoggedIn: bool): VNode = let postCopy = post # TODO: Another workaround here, closure capture :( result = buildHtml(): @@ -94,31 +135,6 @@ when defined(js): italic(class="fas fa-reply") text " Reply" - proc onLoadMore(ev: Event, n: VNode) = - if state.loading: return - - state.loading = true - let start = n.getAttr("data-start").parseInt() - let threadId = state.list.get().thread.id - let uri = makeUri("posts.json", [("start", $start), ("id", $threadId)]) - ajaxGet(uri, @[], (s: int, r: kstring) => onPostList(s, r, start)) - - proc genLoadMore(start: int): VNode = - result = buildHtml(): - tdiv(class="information load-more-posts", - onClick=onLoadMore, - "data-start" = $start): - tdiv(class="information-icon"): - italic(class="fas fa-comment-dots") - tdiv(class="information-main"): - if state.loading: - tdiv(class="loading loading-lg") - else: - tdiv(class="information-title"): - text "Load more posts " - span(class="more-post-count"): - text "(" & $state.list.get().moreCount & ")" - proc genTimePassed(prevPost: Post, post: Option[Post]): VNode = var latestTime = if post.isSome: post.get().info.creation.fromUnix() @@ -153,7 +169,7 @@ when defined(js): if state.list.isNone or state.list.get().thread.id != threadId: let uri = makeUri("posts.json", ("id", $threadId)) - ajaxGet(uri, @[], (s: int, r: kstring) => onPostList(s, r, 0)) + ajaxGet(uri, @[], (s: int, r: kstring) => onPostList(s, r)) return buildHtml(tdiv(class="loading loading-lg")) @@ -165,16 +181,15 @@ when defined(js): render(list.thread.category) tdiv(class="posts"): var prevPost: Option[Post] = none[Post]() - for post in list.posts: + for i, post in list.posts: if prevPost.isSome: genTimePassed(prevPost.get(), some(post)) + if post.moreBefore.len > 0: + genLoadMore(post, i) genPost(post, list.thread, isLoggedIn) prevPost = some(post) - let hasMore = list.moreCount > 0 - if hasMore: - genLoadMore(list.posts.len) - elif prevPost.isSome: + if prevPost.isSome: genTimePassed(prevPost.get(), none[Post]()) - render(state.replyBox, list.thread, state.replyingTo, hasMore) \ No newline at end of file + render(state.replyBox, list.thread, state.replyingTo, false) \ No newline at end of file