Working post preview!
This commit is contained in:
parent
53c0bd89b9
commit
4ff5df6be2
4 changed files with 94 additions and 13 deletions
25
forum.nim
25
forum.nim
|
|
@ -14,7 +14,7 @@ import cgi except setCookie
|
||||||
import options
|
import options
|
||||||
|
|
||||||
import redesign/threadlist except User
|
import redesign/threadlist except User
|
||||||
import redesign/[category, postlist, error, header]
|
import redesign/[category, postlist, error, header, post]
|
||||||
|
|
||||||
when not defined(windows):
|
when not defined(windows):
|
||||||
import bcrypt # TODO
|
import bcrypt # TODO
|
||||||
|
|
@ -1186,6 +1186,29 @@ routes:
|
||||||
let status = UserStatus(user: user)
|
let status = UserStatus(user: user)
|
||||||
resp $(%status), "application/json"
|
resp $(%status), "application/json"
|
||||||
|
|
||||||
|
post "/karax/preview":
|
||||||
|
createTFD()
|
||||||
|
if not c.loggedIn():
|
||||||
|
let err = PostError(
|
||||||
|
errorFields: @[],
|
||||||
|
message: "Not logged in."
|
||||||
|
)
|
||||||
|
resp Http401, $(%err), "application/json"
|
||||||
|
|
||||||
|
let formData = request.formData
|
||||||
|
cond "msg" in formData
|
||||||
|
|
||||||
|
let msg = formData["msg"].body
|
||||||
|
try:
|
||||||
|
let rendered = msg.rstToHtml()
|
||||||
|
resp Http200, rendered
|
||||||
|
except EParseError:
|
||||||
|
let err = PostError(
|
||||||
|
errorFields: @[],
|
||||||
|
message: getCurrentExceptionMsg()
|
||||||
|
)
|
||||||
|
resp Http400, $(%err), "application/json"
|
||||||
|
|
||||||
get re"/karax/(.+)?":
|
get re"/karax/(.+)?":
|
||||||
resp readFile("redesign/karax.html")
|
resp readFile("redesign/karax.html")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,11 @@ proc anchorCB*(e: kdom.Event, n: VNode) = # TODO: Why does this need disamb?
|
||||||
|
|
||||||
type
|
type
|
||||||
FormData* = ref object
|
FormData* = ref object
|
||||||
|
proc newFormData*(): FormData
|
||||||
|
{.importcpp: "new FormData()", constructor.}
|
||||||
proc newFormData*(form: dom.Element): FormData
|
proc newFormData*(form: dom.Element): FormData
|
||||||
{.importcpp: "new FormData(@)", constructor.}
|
{.importcpp: "new FormData(@)", constructor.}
|
||||||
proc get*(form: FormData, key: cstring): cstring
|
proc get*(form: FormData, key: cstring): cstring
|
||||||
{.importcpp: "#.get(@)".}
|
{.importcpp: "#.get(@)".}
|
||||||
|
proc append*(form: FormData, key, val: cstring)
|
||||||
|
{.importcpp: "#.append(@)".}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import strformat
|
import strformat
|
||||||
|
|
||||||
import threadlist
|
import threadlist
|
||||||
import karaxutils
|
|
||||||
|
|
||||||
type
|
type
|
||||||
PostInfo* = object
|
PostInfo* = object
|
||||||
|
|
@ -20,5 +20,8 @@ type
|
||||||
## older versions of the post.
|
## older versions of the post.
|
||||||
info*: PostInfo
|
info*: PostInfo
|
||||||
|
|
||||||
proc renderPostUrl*(post: Post, thread: Thread): string =
|
|
||||||
makeUri(fmt"/t/{thread.id}#{post.id}")
|
when defined(js):
|
||||||
|
import karaxutils
|
||||||
|
proc renderPostUrl*(post: Post, thread: Thread): string =
|
||||||
|
makeUri(fmt"/t/{thread.id}#{post.id}")
|
||||||
|
|
@ -1,20 +1,26 @@
|
||||||
when defined(js):
|
when defined(js):
|
||||||
import strformat, options
|
import strformat, options, httpcore, json, sugar
|
||||||
|
|
||||||
from dom import getElementById, scrollIntoView, setTimeout
|
from dom import getElementById, scrollIntoView, setTimeout
|
||||||
|
|
||||||
include karax/prelude
|
include karax/prelude
|
||||||
import karax / [vstyles, kajax, kdom]
|
import karax / [vstyles, kajax, kdom]
|
||||||
|
|
||||||
import karaxutils, threadlist, post
|
import karaxutils, threadlist, post, error
|
||||||
|
|
||||||
type
|
type
|
||||||
ReplyBox* = ref object
|
ReplyBox* = ref object
|
||||||
shown: bool
|
shown: bool
|
||||||
|
text: kstring
|
||||||
preview: bool
|
preview: bool
|
||||||
|
loading: bool
|
||||||
|
error: Option[PostError]
|
||||||
|
rendering: Option[kstring]
|
||||||
|
|
||||||
proc newReplyBox*(): ReplyBox =
|
proc newReplyBox*(): ReplyBox =
|
||||||
ReplyBox()
|
ReplyBox(
|
||||||
|
text: ""
|
||||||
|
)
|
||||||
|
|
||||||
proc performScroll() =
|
proc performScroll() =
|
||||||
let replyBox = dom.document.getElementById("reply-box")
|
let replyBox = dom.document.getElementById("reply-box")
|
||||||
|
|
@ -31,6 +37,39 @@ when defined(js):
|
||||||
|
|
||||||
state.shown = true
|
state.shown = true
|
||||||
|
|
||||||
|
proc onPreviewPost(httpStatus: int, response: kstring, state: ReplyBox) =
|
||||||
|
let status = httpStatus.HttpCode
|
||||||
|
if status == Http200:
|
||||||
|
kout(response)
|
||||||
|
state.rendering = some[kstring](response)
|
||||||
|
else:
|
||||||
|
# TODO: login has similar code, abstract this.
|
||||||
|
try:
|
||||||
|
let parsed = parseJson($response)
|
||||||
|
let error = to(parsed, PostError)
|
||||||
|
|
||||||
|
state.error = some(error)
|
||||||
|
except:
|
||||||
|
kout(getCurrentExceptionMsg().cstring)
|
||||||
|
state.error = some(PostError(
|
||||||
|
errorFields: @[],
|
||||||
|
message: "Unknown error occurred."
|
||||||
|
))
|
||||||
|
|
||||||
|
proc onPreviewClick(e: Event, n: VNode, state: ReplyBox) =
|
||||||
|
state.preview = true
|
||||||
|
|
||||||
|
let formData = newFormData()
|
||||||
|
formData.append("msg", state.text)
|
||||||
|
let uri = makeUri("/preview")
|
||||||
|
ajaxPost(uri, @[], cast[cstring](formData),
|
||||||
|
(s: int, r: kstring) => onPreviewPost(s, r, state))
|
||||||
|
|
||||||
|
proc onChange(e: Event, n: VNode, state: ReplyBox) =
|
||||||
|
# TODO: There should be a karax-way to do this. I guess I can just call
|
||||||
|
# `value` on the node? We need to document this better :)
|
||||||
|
state.text = cast[dom.TextAreaElement](n.dom).value
|
||||||
|
|
||||||
proc render*(state: ReplyBox, thread: Thread, post: Option[Post],
|
proc render*(state: ReplyBox, thread: Thread, post: Option[Post],
|
||||||
hasMore: bool): VNode =
|
hasMore: bool): VNode =
|
||||||
if not state.shown:
|
if not state.shown:
|
||||||
|
|
@ -56,14 +95,26 @@ when defined(js):
|
||||||
tdiv(class="panel"):
|
tdiv(class="panel"):
|
||||||
tdiv(class="panel-nav"):
|
tdiv(class="panel-nav"):
|
||||||
ul(class="tab tab-block"):
|
ul(class="tab tab-block"):
|
||||||
li(class=class({"active": not state.preview}, "tab-item")):
|
li(class=class({"active": not state.preview}, "tab-item"),
|
||||||
a(href="#"):
|
onClick=(e: Event, n: VNode) => (state.preview = false)):
|
||||||
|
a(class="c-hand"):
|
||||||
text "Message"
|
text "Message"
|
||||||
li(class=class({"active": state.preview}, "tab-item")):
|
li(class=class({"active": state.preview}, "tab-item"),
|
||||||
a(href="#"):
|
onClick=(e: Event, n: VNode) =>
|
||||||
|
onPreviewClick(e, n, state)):
|
||||||
|
a(class="c-hand"):
|
||||||
text "Preview"
|
text "Preview"
|
||||||
tdiv(class="panel-body"):
|
tdiv(class="panel-body"):
|
||||||
textarea(class="form-input", rows="5")
|
if state.preview:
|
||||||
|
if state.loading:
|
||||||
|
tdiv(class="loading")
|
||||||
|
elif state.rendering.isSome():
|
||||||
|
verbatim(state.rendering.get())
|
||||||
|
else:
|
||||||
|
textarea(class="form-input", rows="5",
|
||||||
|
onChange=(e: Event, n: VNode) =>
|
||||||
|
onChange(e, n, state),
|
||||||
|
value=state.text)
|
||||||
tdiv(class="panel-footer"):
|
tdiv(class="panel-footer"):
|
||||||
button(class="btn btn-primary float-right"):
|
button(class="btn btn-primary float-right"):
|
||||||
text "Reply"
|
text "Reply"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue