nimforum/redesign/header.nim
2018-05-12 14:08:08 +01:00

107 lines
No EOL
3.1 KiB
Nim

import options, times, httpcore, json, sugar
import threadlist
type
UserStatus* = object
user*: Option[User]
when defined(js):
include karax/prelude
import karax / [kajax]
import login, signup, usermenu
import karaxutils
from dom import setTimeout, window, document, getElementById, focus
type
State = ref object
data: Option[UserStatus]
loading: bool
status: HttpCode
lastUpdate: Time
loginModal: LoginModal
signupModal: SignupModal
userMenu: UserMenu
proc newState(): State
var
state = newState()
proc getStatus(logout: bool=false)
proc newState(): State =
State(
data: none[UserStatus](),
loading: false,
status: Http200,
loginModal: newLoginModal(
() => (state.lastUpdate = fromUnix(0); getStatus()),
() => state.signupModal.show()
),
signupModal: newSignupModal(
() => (state.lastUpdate = fromUnix(0); getStatus()),
() => state.loginModal.show()
),
userMenu: newUserMenu(
() => (state.lastUpdate = fromUnix(0); getStatus(logout=true))
)
)
proc onStatus(httpStatus: int, response: kstring) =
state.loading = false
state.status = httpStatus.HttpCode
if state.status != Http200: return
let parsed = parseJson($response)
state.data = some(to(parsed, UserStatus))
state.lastUpdate = getTime()
proc getStatus(logout: bool=false) =
if state.loading: return
let diff = getTime() - state.lastUpdate
if diff.minutes < 5:
return
state.loading = true
let uri = makeUri("status.json", [("logout", $logout)])
ajaxGet(uri, @[], onStatus)
proc isLoggedIn*(): bool =
let user = state.data.map(x => x.user).flatten
not user.isNone
proc renderHeader*(): VNode =
if state.data.isNone:
getStatus() # TODO: Call this every render?
let user = state.data.map(x => x.user).flatten
result = buildHtml(tdiv()): # TODO: Why do some buildHtml's need this?
header(id="main-navbar"):
tdiv(class="navbar container grid-xl"):
section(class="navbar-section"):
a(href=makeUri("/")):
img(src="/karax/images/crown.png", id="img-logo") # TODO: Customisation.
section(class="navbar-section"):
tdiv(class="input-group input-inline"):
input(class="search-input input-sm",
`type`="text", placeholder="search",
id="search-box")
if state.loading:
tdiv(class="loading")
elif user.isNone:
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")
text " Log in"
else:
render(state.userMenu, user.get())
# Modals
render(state.loginModal)
render(state.signupModal)