Reimplement sign up form.

This commit is contained in:
Dominik Picheta 2018-05-11 16:15:13 +01:00
commit 01253244f7
5 changed files with 136 additions and 63 deletions

View file

@ -1,3 +1,4 @@
import options
type
PostError* = object
errorFields*: seq[string] ## IDs of the fields with an error.
@ -7,6 +8,8 @@ when defined(js):
include karax/prelude
import karax / [vstyles, kajax, kdom]
import karaxutils
proc renderError*(message: string): VNode =
result = buildHtml():
tdiv(class="empty error"):
@ -19,4 +22,22 @@ when defined(js):
tdiv(class="empty-action"):
a(href="https://github.com/nim-lang/nimforum/issues", target="_blank"):
button(class="btn btn-primary"):
text "Report issue"
text "Report issue"
proc genFormField*(error: Option[PostError], name, label, typ: string,
isLast: bool): VNode =
let hasError =
not error.isNone and (
name in error.get().errorFields or
error.get().errorFields.len == 0)
result = buildHtml():
tdiv(class=class({"has-error": hasError}, "form-group")):
label(class="form-label", `for`=name):
text label
input(class="form-input", `type`="text", name=name)
if not error.isNone:
let e = error.get()
if (e.errorFields.len == 1 and e.errorFields[0] == name) or isLast:
p(class="form-input-hint"):
text e.message

View file

@ -9,7 +9,7 @@ when defined(js):
include karax/prelude
import karax / [kajax]
import login
import login, signup
import karaxutils
from dom import setTimeout, window, document, getElementById, focus
@ -21,6 +21,7 @@ when defined(js):
status: HttpCode
lastUpdate: Time
loginModal: LoginModal
signupModal: SignupModal
proc newState(): State
var
@ -33,7 +34,12 @@ when defined(js):
loading: false,
status: Http200,
loginModal: newLoginModal(
() => (state.lastUpdate = fromUnix(0); getStatus())
() => (state.lastUpdate = fromUnix(0); getStatus()),
() => state.signupModal.show()
),
signupModal: newSignupModal(
() => (state.lastUpdate = fromUnix(0); getStatus()),
() => state.loginModal.show()
)
)
@ -57,37 +63,6 @@ when defined(js):
let uri = makeUri("status.json")
ajaxGet(uri, @[], onStatus)
proc genSignUpModal(): VNode =
result = buildHtml():
tdiv(class="modal", id="signup-modal"):
a(href="#", class="modal-overlay", "aria-label"="close")
tdiv(class="modal-container"):
tdiv(class="modal-header"):
a(href="#", class="btn btn-clear float-right", "aria-label"="close")
tdiv(class="modal-title h5"):
text "Create a new account"
tdiv(class="modal-body"):
tdiv(class="content"):
form():
tdiv(class="form-group"):
label(class="form-label", `for`="email"):
text "Email"
input(class="form-input", `type`="text", name="email")
tdiv(class="form-group"):
label(class="form-label", `for`="regusername"):
text "Username"
input(class="form-input", `type`="text", name="username")
tdiv(class="form-group"):
label(class="form-label", `for`="regpassword"):
text "Password"
input(class="form-input", `type`="password", name="password")
tdiv(class="modal-footer"):
button(class="btn btn-primary"):
text "Create account"
a(href="#login-modal"):
button(class="btn"):
text "Log in"
proc renderHeader*(): VNode =
if state.data.isNone:
getStatus()
@ -107,10 +82,10 @@ when defined(js):
if state.loading:
tdiv(class="loading")
elif user.isNone:
a(href="#signup-modal", id="signup-btn"):
button(class="btn btn-primary btn-sm"):
italic(class="fas fa-user-plus")
text " Sign up"
button(class="btn btn-primary btn-sm",
onClick=(e: Event, n: VNode) => state.signupModal.show()):
italic(class="fas fa-user-plus")
text " Sign up"
button(class="btn btn-primary btn-sm",
onClick=(e: Event, n: VNode) => state.loginModal.show()):
italic(class="fas fa-sign-in-alt")
@ -121,4 +96,4 @@ when defined(js):
# Modals
render(state.loginModal)
genSignUpModal()
render(state.signupModal)

View file

@ -1,4 +1,4 @@
import strutils
import strutils, options
import dom except window
include karax/prelude

View file

@ -12,6 +12,7 @@ when defined(js):
LoginModal* = ref object
shown: bool
onLogIn: proc ()
onSignUp: proc ()
error: Option[PostError]
proc onLogInPost(httpStatus: int, response: kstring, state: LoginModal) =
@ -47,33 +48,16 @@ when defined(js):
state.shown = false
ev.preventDefault()
proc newLoginModal*(onLogIn: proc ()): LoginModal =
proc newLoginModal*(onLogIn, onSignUp: proc ()): LoginModal =
LoginModal(
shown: false,
onLogIn: onLogIn
onLogIn: onLogIn,
onSignUp: onSignUp
)
proc show*(state: LoginModal) =
state.shown = true
proc genFormField(error: Option[PostError], name, label, typ: string,
isLast: bool): VNode =
let hasError =
not error.isNone and (
name in error.get().errorFields or
error.get().errorFields.len == 0)
result = buildHtml():
tdiv(class=class({"has-error": hasError}, "form-group")):
label(class="form-label", `for`=name):
text "Username"
input(class="form-input", `type`="text", name=name)
if not error.isNone:
let e = error.get()
if (e.errorFields.len == 1 and e.errorFields[0] == name) or isLast:
p(class="form-input-hint"):
text e.message
proc render*(state: LoginModal): VNode =
result = buildHtml():
tdiv(class=class({"active": state.shown}, "modal modal-sm"),
@ -104,6 +88,7 @@ when defined(js):
button(class="btn btn-primary",
onClick=(ev: Event, n: VNode) => onLogInClick(ev, n, state)):
text "Log in"
a(href="#signup-modal"):
button(class="btn"):
text "Create account"
button(class="btn",
onClick=(ev: Event, n: VNode) =>
(state.onSignUp(); state.shown = false)):
text "Create account"

92
redesign/signup.nim Normal file
View file

@ -0,0 +1,92 @@
when defined(js):
import sugar, httpcore, options, json
import dom except Event
include karax/prelude
import karax / [kajax, kdom]
import error
import karaxutils
type
SignupModal* = ref object
shown: bool
onSignUp, onLogIn: proc ()
error: Option[PostError]
proc onSignUpPost(httpStatus: int, response: kstring, state: SignupModal) =
let status = httpStatus.HttpCode
if status == Http200:
state.shown = false
state.onSignUp()
else:
# TODO: Karax should pass the content-type...
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 onSignUpClick(ev: Event, n: VNode, state: SignupModal) =
state.error = none[PostError]()
let uri = makeUri("signup")
let form = dom.document.getElementById("signup-form")
# TODO: This is a hack, karax should support this.
let formData = newFormData(form)
ajaxPost(uri, @[], cast[cstring](formData),
(s: int, r: kstring) => onSignUpPost(s, r, state))
proc onClose(ev: Event, n: VNode, state: SignupModal) =
state.shown = false
ev.preventDefault()
proc newSignupModal*(onSignUp, onLogIn: proc ()): SignupModal =
SignupModal(
shown: false,
onLogIn: onLogIn,
onSignUp: onSignUp
)
proc show*(state: SignupModal) =
state.shown = true
proc render*(state: SignupModal): VNode =
result = buildHtml():
tdiv(class=class({"active": state.shown}, "modal modal-sm"),
id="signup-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 "Create a new account"
tdiv(class="modal-body"):
tdiv(class="content"):
form(id="signup-form"):
genFormField(state.error, "email", "Email", "email", false)
genFormField(state.error, "username", "Username", "text", false)
genFormField(
state.error,
"password",
"Password",
"password",
true
)
tdiv(class="modal-footer"):
button(class="btn btn-primary",
onClick=(ev: Event, n: VNode) => onSignUpClick(ev, n, state)):
text "Create account"
button(class="btn",
onClick=(ev: Event, n: VNode) =>
(state.onLogIn(); state.shown = false)):
text "Log in"