Implements edit box and rearranges post buttons.

This commit is contained in:
Dominik Picheta 2018-05-16 18:45:42 +01:00
commit c5fd70d275
5 changed files with 108 additions and 16 deletions

View file

@ -1258,6 +1258,21 @@ routes:
resp $(%list), "application/json"
get "/karax/post.rst":
createTFD()
let postId = getInt(@"id", -1)
cond postId != -1
let postQuery = sql"""
select content from post where id = ?;
"""
let content = getValue(db, postQuery, postId)
if content.len == 0:
resp Http404, "Post not found"
else:
resp content, "text/x-rst"
get "/karax/profile.json":
createTFD()
var

43
redesign/editbox.nim Normal file
View file

@ -0,0 +1,43 @@
when defined(js):
import httpcore, options, sugar
include karax/prelude
import karax/kajax
import replybox, post, karaxutils, threadlist
type
EditBox* = ref object
box: ReplyBox
post: Option[Post]
rawContent: Option[kstring] ## The raw rst for a post (needs to be loaded)
status: HttpCode
proc newEditBox*(): EditBox =
EditBox(
box: newReplyBox(nil)
)
proc onRawContent(httpStatus: int, response: kstring, state: EditBox) =
state.status = httpStatus.HttpCode
if state.status != Http200: return
state.rawContent = some(response)
proc render*(state: EditBox, post: Post): VNode =
if state.post.isNone() or state.post.get().id != post.id:
state.post = some(post)
var params = @[("id", $post.id)]
let uri = makeUri("post.rst", params)
ajaxGet(uri, @[], (s: int, r: kstring) => onRawContent(s, r, state))
return buildHtml(tdiv(class="loading"))
state.box.setText(state.rawContent.get())
result = buildHtml():
tdiv(class="edit-box"):
renderContent(
state.box,
none[Thread](),
none[Post]()
)

View file

@ -63,7 +63,7 @@ proc render(): VNode =
renderPostList(
params["id"].parseInt(),
if postId == 0: none[int]() else: some[int](postId),
isLoggedIn()
getLoggedInUser()
)
)
),

View file

@ -17,7 +17,7 @@ when defined(js):
include karax/prelude
import karax / [vstyles, kajax, kdom]
import karaxutils, error, replybox
import karaxutils, error, replybox, editbox
type
State = ref object
@ -26,6 +26,8 @@ when defined(js):
status: HttpCode
replyingTo: Option[Post]
replyBox: ReplyBox
editing: Option[Post] ## If in edit mode, this contains the post.
editBox: EditBox
proc onReplyPosted(id: int)
proc newState(): State =
@ -34,7 +36,8 @@ when defined(js):
loading: false,
status: Http200,
replyingTo: none[Post](),
replyBox: newReplyBox(onReplyPosted)
replyBox: newReplyBox(onReplyPosted),
editBox: newEditBox()
)
var
@ -106,10 +109,21 @@ when defined(js):
## Executed when a reply has been successfully posted.
loadMore(state.list.get().posts.len, @[id])
proc onEditPosted(id: int, content: string) =
## Executed when an edit has been successfully posted.
let list = state.list.get()
for i in 0 ..< list.posts.len:
if list.posts[i].id == id:
list.posts[i].info.content = content
break
proc onReplyClick(e: Event, n: VNode, p: Option[Post]) =
state.replyingTo = p
state.replyBox.show()
proc onEditClick(e: Event, n: VNode, p: Option[Post]) =
state.editing = p
proc onLoadMore(ev: Event, n: VNode, start: int, post: Post) =
loadMore(start, post.moreBefore) # TODO: Don't load all!
@ -128,8 +142,12 @@ when defined(js):
span(class="more-post-count"):
text "(" & $post.moreBefore.len & ")"
proc genPost(post: Post, thread: Thread, isLoggedIn: bool): VNode =
proc genPost(post: Post, thread: Thread, currentUser: Option[User]): VNode =
let postCopy = post # TODO: Another workaround here, closure capture :(
let loggedIn = currentUser.isSome()
let authoredByUser =
loggedIn and currentUser.get().name == post.author.name
result = buildHtml():
tdiv(class="post", id = $post.id):
tdiv(class="post-icon"):
@ -144,18 +162,33 @@ when defined(js):
a(href=renderPostUrl(post, thread), title=title):
text renderActivity(post.info.creation)
tdiv(class="post-content"):
verbatim(post.info.content)
if state.editing.isSome() and state.editing.get() == post:
render(state.editBox, postCopy)
else:
verbatim(post.info.content)
tdiv(class="post-buttons"):
tdiv(class="like-button"):
button(class="btn"):
span(class="like-count"):
if post.likes.len > 0:
text $post.likes.len
italic(class="far fa-heart")
if isLoggedIn:
tdiv(class="flag-button"):
if authoredByUser:
tdiv(class="edit-button", onClick=(e: Event, n: VNode) =>
onEditClick(e, n, some(postCopy))):
button(class="btn"):
italic(class="far fa-flag")
italic(class="far fa-edit")
tdiv(class="delete-button"):
button(class="btn"):
italic(class="far fa-trash-alt")
else:
tdiv(class="like-button"):
button(class="btn"):
span(class="like-count"):
if post.likes.len > 0:
text $post.likes.len
italic(class="far fa-heart")
if loggedIn:
tdiv(class="flag-button"):
button(class="btn"):
italic(class="far fa-flag")
if loggedIn:
tdiv(class="reply-button"):
button(class="btn", onClick=(e: Event, n: VNode) =>
onReplyClick(e, n, some(postCopy))):
@ -205,7 +238,7 @@ when defined(js):
text diffStr
proc renderPostList*(threadId: int, postId: Option[int],
isLoggedIn: bool): VNode =
currentUser: Option[User]): VNode =
if state.status != Http200:
return renderError("Couldn't retrieve posts.")
@ -243,7 +276,7 @@ when defined(js):
genTimePassed(prevPost.get(), some(post), false)
if post.moreBefore.len > 0:
genLoadMore(post, i)
genPost(post, list.thread, isLoggedIn)
genPost(post, list.thread, currentUser)
prevPost = some(post)
if prevPost.isSome:

View file

@ -40,6 +40,7 @@ when defined(js):
state.shown = true
proc getText*(state: ReplyBox): kstring = state.text
proc setText*(state: ReplyBox, text: kstring) = state.text = text
proc onPreviewPost(httpStatus: int, response: kstring, state: ReplyBox) =
postFinished: