Implements new thread modal.

This commit is contained in:
Dominik Picheta 2018-05-15 19:40:07 +01:00
commit c966ec8f92
4 changed files with 163 additions and 45 deletions

81
redesign/newthread.nim Normal file
View file

@ -0,0 +1,81 @@
when defined(js):
import sugar, httpcore, options, json
import dom except Event
include karax/prelude
import karax / [kajax, kdom]
import error, replybox, threadlist, post
import karaxutils
type
NewThreadModal* = ref object
shown: bool
loading: bool
onNewThread: proc (threadId, postId: int)
error: Option[PostError]
replyBox: ReplyBox
proc onCreatePost(httpStatus: int, response: kstring, state: NewThreadModal) =
postFinished:
state.shown = false
state.onNewThread(0, 0) # TODO
proc onCreateClick(ev: Event, n: VNode, state: NewThreadModal) =
state.loading = true
state.error = none[PostError]()
let uri = makeUri("login")
# TODO: This is a hack, karax should support this.
let formData = newFormData()
#formData.append("" TODO
ajaxPost(uri, @[], cast[cstring](formData),
(s: int, r: kstring) => onCreatePost(s, r, state))
proc onClose(ev: Event, n: VNode, state: NewThreadModal) =
state.shown = false
ev.preventDefault()
proc newNewThreadModal*(
onNewThread: proc (threadId, postId: int)
): NewThreadModal =
NewThreadModal(
shown: false,
onNewThread: onNewThread,
replyBox: newReplyBox(nil)
)
proc show*(state: NewThreadModal) =
state.shown = true
proc render*(state: NewThreadModal): VNode =
result = buildHtml():
tdiv(class=class({"active": state.shown}, "modal modal-lg"),
id="new-thread-modal"):
a(href="", class="modal-overlay", "aria-label"="close",
onClick=(ev: Event, n: VNode) => onClose(ev, n, state))
tdiv(class="modal-container"):
tdiv(class="modal-header"):
a(href="", class="btn btn-clear float-right",
"aria-label"="close",
onClick=(ev: Event, n: VNode) => onClose(ev, n, state))
tdiv(class="modal-title h5"):
text "New Thread"
tdiv(class="modal-body"):
tdiv(class="content"):
input(class="form-input", `type`="text", name="username",
placeholder="Type the title here")
renderContent(state.replyBox, none[Thread](), none[Post]())
tdiv(class="modal-footer"):
button(class="btn",
onClick=(ev: Event, n: VNode) =>
onClose(ev, n, state)):
text "Cancel"
button(class=class(
{"loading": state.loading},
"btn btn-primary"
),
onClick=(ev: Event, n: VNode) =>
(onCreateClick(ev, n, state))):
text "Create thread"

View file

@ -113,6 +113,23 @@ $logo-height: $navbar-height - 20px;
}
}
#new-thread-modal {
.modal-container .modal-body {
max-height: none;
}
.form-input {
margin-bottom: $control-padding-y*2;
}
textarea.form-input, .panel-body > div {
margin-top: $control-padding-y*2;
resize: none;
min-height: 40vh;
max-height: 45vh;
}
}
// - Thread table
.thread-title {
a, a:visited, a:hover {

View file

@ -48,6 +48,7 @@ when defined(js):
state.preview = true
state.loading = true
state.error = none[PostError]()
state.rendering = none[kstring]()
let formData = newFormData()
formData.append("msg", state.text)
@ -55,6 +56,10 @@ when defined(js):
ajaxPost(uri, @[], cast[cstring](formData),
(s: int, r: kstring) => onPreviewPost(s, r, state))
proc onMessageClick(e: Event, n: VNode, state: ReplyBox) =
state.preview = false
state.error = none[PostError]()
proc onReplyPost(httpStatus: int, response: kstring, state: ReplyBox) =
postFinished:
state.text = ""
@ -84,6 +89,53 @@ when defined(js):
# `value` on the node? We need to document this better :)
state.text = cast[dom.TextAreaElement](n.dom).value
proc renderContent*(state: ReplyBox, thread: Option[Thread],
post: Option[Post]): VNode =
result = buildHtml():
tdiv(class="panel"):
tdiv(class="panel-nav"):
ul(class="tab tab-block"):
li(class=class({"active": not state.preview}, "tab-item"),
onClick=(e: Event, n: VNode) =>
onMessageClick(e, n, state)):
a(class="c-hand"):
text "Message"
li(class=class({"active": state.preview}, "tab-item"),
onClick=(e: Event, n: VNode) =>
onPreviewClick(e, n, state)):
a(class="c-hand"):
text "Preview"
tdiv(class="panel-body"):
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)
if state.error.isSome():
p(class="text-error",
style=style(StyleAttr.marginTop, "0.4rem")):
text state.error.get().message
if thread.isSome:
tdiv(class="panel-footer"):
button(class=class(
{"loading": state.loading},
"btn btn-primary float-right"
),
onClick=(e: Event, n: VNode) =>
onReplyClick(e, n, state, thread.get(), post)):
text "Reply"
button(class="btn btn-link float-right",
onClick=(e: Event, n: VNode) =>
onCancelClick(e, n, state)):
text "Cancel"
proc render*(state: ReplyBox, thread: Thread, post: Option[Post],
hasMore: bool): VNode =
if not state.shown:
@ -106,44 +158,4 @@ when defined(js):
button(class="btn"):
italic(class="fas fa-arrow-up")
tdiv(class="information-content"):
tdiv(class="panel"):
tdiv(class="panel-nav"):
ul(class="tab tab-block"):
li(class=class({"active": not state.preview}, "tab-item"),
onClick=(e: Event, n: VNode) => (state.preview = false)):
a(class="c-hand"):
text "Message"
li(class=class({"active": state.preview}, "tab-item"),
onClick=(e: Event, n: VNode) =>
onPreviewClick(e, n, state)):
a(class="c-hand"):
text "Preview"
tdiv(class="panel-body"):
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)
if state.error.isSome():
tdiv(class="toast toast-error",
style=style(StyleAttr.marginTop, "0.4rem")):
text state.error.get().message
tdiv(class="panel-footer"):
button(class=class(
{"loading": state.loading},
"btn btn-primary float-right"
),
onClick=(e: Event, n: VNode) =>
onReplyClick(e, n, state, thread, post)):
text "Reply"
button(class="btn btn-link float-right",
onClick=(e: Event, n: VNode) =>
onCancelClick(e, n, state)):
text "Cancel"
renderContent(state, some(thread), post)

View file

@ -24,24 +24,30 @@ when defined(js):
include karax/prelude
import karax / [vstyles, kajax, kdom]
import karaxutils, error
import karaxutils, error, newthread
type
State = ref object
list: Option[ThreadList]
loading: bool
status: HttpCode
newThread: NewThreadModal
proc onNewThread(threadId, postId: int)
proc newState(): State =
State(
list: none[ThreadList](),
loading: false,
status: Http200
status: Http200,
newThread: newNewThreadModal(onNewThread)
)
var
state = newState()
proc onNewThread(threadId, postId: int) =
discard
proc genTopButtons(): VNode =
result = buildHtml():
section(class="navbar container grid-xl", id="main-buttons"):
@ -57,7 +63,8 @@ when defined(js):
button(class="btn btn-link"): text "Most Active"
button(class="btn btn-link"): text "Categories"
section(class="navbar-section"):
button(class="btn btn-secondary"):
button(class="btn btn-secondary",
onClick=(e: Event, n: VNode) => state.newThread.show()):
italic(class="fas fa-plus")
text " New Thread"
@ -174,4 +181,5 @@ when defined(js):
proc renderThreadList*(): VNode =
result = buildHtml(tdiv):
genTopButtons()
genThreadList()
genThreadList()
render(state.newThread)