Remove reloading and fix issues with state not being refreshed (#232)
* Remove reloading and fix issues with state not being refreshed * Fix PR comments * Remove unnecessary closure * Change proc to anonymous proc * categoryIdOption -> categoryId
This commit is contained in:
parent
7a7a7145ee
commit
b91bdeb450
7 changed files with 50 additions and 48 deletions
|
|
@ -13,6 +13,7 @@ when defined(js):
|
||||||
State = ref object
|
State = ref object
|
||||||
list: Option[CategoryList]
|
list: Option[CategoryList]
|
||||||
loading: bool
|
loading: bool
|
||||||
|
mainButtons: MainButtons
|
||||||
status: HttpCode
|
status: HttpCode
|
||||||
addCategoryModal: AddCategoryModal
|
addCategoryModal: AddCategoryModal
|
||||||
|
|
||||||
|
|
@ -22,6 +23,7 @@ when defined(js):
|
||||||
State(
|
State(
|
||||||
list: none[CategoryList](),
|
list: none[CategoryList](),
|
||||||
loading: false,
|
loading: false,
|
||||||
|
mainButtons: newMainButtons(),
|
||||||
status: Http200,
|
status: Http200,
|
||||||
addCategoryModal: newAddCategoryModal(
|
addCategoryModal: newAddCategoryModal(
|
||||||
onAddCategory=
|
onAddCategory=
|
||||||
|
|
@ -99,5 +101,5 @@ when defined(js):
|
||||||
|
|
||||||
proc renderCategoryList*(currentUser: Option[User]): VNode =
|
proc renderCategoryList*(currentUser: Option[User]): VNode =
|
||||||
result = buildHtml(tdiv):
|
result = buildHtml(tdiv):
|
||||||
renderMainButtons(currentUser)
|
state.mainButtons.render(currentUser)
|
||||||
renderCategories(currentUser)
|
renderCategories(currentUser)
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,7 @@ when defined(js):
|
||||||
render(state.addCategoryModal)
|
render(state.addCategoryModal)
|
||||||
|
|
||||||
proc render*(state: CategoryPicker, currentUser: Option[User], compact=true): VNode =
|
proc render*(state: CategoryPicker, currentUser: Option[User], compact=true): VNode =
|
||||||
if currentUser.isAdmin():
|
state.setAddEnabled(currentUser.isAdmin())
|
||||||
state.setAddEnabled(true)
|
|
||||||
|
|
||||||
if state.status != Http200:
|
if state.status != Http200:
|
||||||
return renderError("Couldn't retrieve categories.", state.status)
|
return renderError("Couldn't retrieve categories.", state.status)
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,6 @@ proc onPopState(event: dom.Event) =
|
||||||
state = newState() # Reload the state to remove stale data.
|
state = newState() # Reload the state to remove stale data.
|
||||||
state.url = copyLocation(window.location)
|
state.url = copyLocation(window.location)
|
||||||
|
|
||||||
# For some reason this is needed so that the back/forward buttons reload
|
|
||||||
# the post list when different categories are selected
|
|
||||||
window.location.reload()
|
|
||||||
|
|
||||||
redraw()
|
redraw()
|
||||||
|
|
||||||
type Params = Table[string, string]
|
type Params = Table[string, string]
|
||||||
|
|
|
||||||
|
|
@ -32,41 +32,36 @@ when defined(js):
|
||||||
var
|
var
|
||||||
state = newState()
|
state = newState()
|
||||||
|
|
||||||
proc getStatus(logout=false, reload=false)
|
proc getStatus(logout=false)
|
||||||
proc newState(): State =
|
proc newState(): State =
|
||||||
State(
|
State(
|
||||||
data: none[UserStatus](),
|
data: none[UserStatus](),
|
||||||
loading: false,
|
loading: false,
|
||||||
status: Http200,
|
status: Http200,
|
||||||
loginModal: newLoginModal(
|
loginModal: newLoginModal(
|
||||||
() => (state.lastUpdate = fromUnix(0); getStatus(reload=true)),
|
() => (state.lastUpdate = fromUnix(0); getStatus()),
|
||||||
() => state.signupModal.show()
|
() => state.signupModal.show()
|
||||||
),
|
),
|
||||||
signupModal: newSignupModal(
|
signupModal: newSignupModal(
|
||||||
() => (state.lastUpdate = fromUnix(0); getStatus(reload=true)),
|
() => (state.lastUpdate = fromUnix(0); getStatus()),
|
||||||
() => state.loginModal.show()
|
() => state.loginModal.show()
|
||||||
),
|
),
|
||||||
userMenu: newUserMenu(
|
userMenu: newUserMenu(
|
||||||
() => (state.lastUpdate = fromUnix(0); getStatus(logout=true, reload=true))
|
() => (state.lastUpdate = fromUnix(0); getStatus(logout=true))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
proc onStatus(reload: bool=false): proc (httpStatus: int, response: kstring) =
|
proc onStatus(httpStatus: int, response: kstring) =
|
||||||
result =
|
state.loading = false
|
||||||
proc (httpStatus: int, response: kstring) =
|
state.status = httpStatus.HttpCode
|
||||||
state.loading = false
|
if state.status != Http200: return
|
||||||
state.status = httpStatus.HttpCode
|
|
||||||
if state.status != Http200: return
|
|
||||||
|
|
||||||
let parsed = parseJson($response)
|
let parsed = parseJson($response)
|
||||||
state.data = some(to(parsed, UserStatus))
|
state.data = some(to(parsed, UserStatus))
|
||||||
|
|
||||||
state.lastUpdate = getTime()
|
state.lastUpdate = getTime()
|
||||||
|
|
||||||
if reload:
|
proc getStatus(logout=false) =
|
||||||
window.location.reload()
|
|
||||||
|
|
||||||
proc getStatus(logout=false, reload=false) =
|
|
||||||
if state.loading: return
|
if state.loading: return
|
||||||
let diff = getTime() - state.lastUpdate
|
let diff = getTime() - state.lastUpdate
|
||||||
if diff.inMinutes < 5:
|
if diff.inMinutes < 5:
|
||||||
|
|
@ -74,7 +69,7 @@ when defined(js):
|
||||||
|
|
||||||
state.loading = true
|
state.loading = true
|
||||||
let uri = makeUri("status.json", [("logout", $logout)])
|
let uri = makeUri("status.json", [("logout", $logout)])
|
||||||
ajaxGet(uri, @[], onStatus(reload))
|
ajaxGet(uri, @[], onStatus)
|
||||||
|
|
||||||
proc getLoggedInUser*(): Option[User] =
|
proc getLoggedInUser*(): Option[User] =
|
||||||
state.data.map(x => x.user).flatten
|
state.data.map(x => x.user).flatten
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,6 @@ when defined(js):
|
||||||
let url = n.getAttr("href")
|
let url = n.getAttr("href")
|
||||||
|
|
||||||
navigateTo(url)
|
navigateTo(url)
|
||||||
window.location.href = url
|
|
||||||
|
|
||||||
proc newFormData*(form: dom.Element): FormData
|
proc newFormData*(form: dom.Element): FormData
|
||||||
{.importcpp: "new FormData(@)", constructor.}
|
{.importcpp: "new FormData(@)", constructor.}
|
||||||
|
|
|
||||||
|
|
@ -17,17 +17,20 @@ when defined(js):
|
||||||
navigateTo(uri)
|
navigateTo(uri)
|
||||||
|
|
||||||
type
|
type
|
||||||
State = ref object
|
MainButtons* = ref object
|
||||||
categoryPicker: CategoryPicker
|
categoryPicker: CategoryPicker
|
||||||
|
onCategoryChange*: CategoryChangeEvent
|
||||||
|
|
||||||
proc newState(): State =
|
proc newMainButtons*(onCategoryChange: CategoryChangeEvent = onSelectedCategoryChanged): MainButtons =
|
||||||
State(
|
new result
|
||||||
categoryPicker: newCategoryPicker(onCategoryChange=onSelectedCategoryChanged),
|
result.onCategoryChange = onCategoryChange
|
||||||
|
result.categoryPicker = newCategoryPicker(
|
||||||
|
onCategoryChange = proc (oldCategory, newCategory: Category) =
|
||||||
|
onSelectedCategoryChanged(oldCategory, newCategory)
|
||||||
|
result.onCategoryChange(oldCategory, newCategory)
|
||||||
)
|
)
|
||||||
|
|
||||||
let state = newState()
|
proc render*(state: MainButtons, currentUser: Option[User], categoryId = none(int)): VNode =
|
||||||
|
|
||||||
proc renderMainButtons*(currentUser: Option[User], categoryIdOption = none(int)): VNode =
|
|
||||||
result = buildHtml():
|
result = buildHtml():
|
||||||
section(class="navbar container grid-xl", id="main-buttons"):
|
section(class="navbar container grid-xl", id="main-buttons"):
|
||||||
section(class="navbar-section"):
|
section(class="navbar-section"):
|
||||||
|
|
@ -38,8 +41,8 @@ when defined(js):
|
||||||
ul(class="menu"):
|
ul(class="menu"):
|
||||||
li: text "community"
|
li: text "community"
|
||||||
li: text "dev" ]#
|
li: text "dev" ]#
|
||||||
if categoryIdOption.isSome:
|
if categoryId.isSome:
|
||||||
state.categoryPicker.selectedCategoryID = categoryIdOption.get()
|
state.categoryPicker.selectedCategoryID = categoryId.get()
|
||||||
render(state.categoryPicker, currentUser, compact=false)
|
render(state.categoryPicker, currentUser, compact=false)
|
||||||
|
|
||||||
for btn in buttons:
|
for btn in buttons:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ proc isModerated*(thread: Thread): bool =
|
||||||
thread.author.rank <= Moderated
|
thread.author.rank <= Moderated
|
||||||
|
|
||||||
when defined(js):
|
when defined(js):
|
||||||
|
import sugar
|
||||||
include karax/prelude
|
include karax/prelude
|
||||||
import karax / [vstyles, kajax, kdom]
|
import karax / [vstyles, kajax, kdom]
|
||||||
|
|
||||||
|
|
@ -34,18 +35,25 @@ when defined(js):
|
||||||
type
|
type
|
||||||
State = ref object
|
State = ref object
|
||||||
list: Option[ThreadList]
|
list: Option[ThreadList]
|
||||||
|
refreshList: bool
|
||||||
loading: bool
|
loading: bool
|
||||||
status: HttpCode
|
status: HttpCode
|
||||||
|
mainButtons: MainButtons
|
||||||
|
|
||||||
|
var state: State
|
||||||
|
|
||||||
proc newState(): State =
|
proc newState(): State =
|
||||||
State(
|
State(
|
||||||
list: none[ThreadList](),
|
list: none[ThreadList](),
|
||||||
loading: false,
|
loading: false,
|
||||||
status: Http200
|
status: Http200,
|
||||||
|
mainButtons: newMainButtons(
|
||||||
|
onCategoryChange =
|
||||||
|
(oldCategory: Category, newCategory: Category) => (state.list = none[ThreadList]())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
var
|
state = newState()
|
||||||
state = newState()
|
|
||||||
|
|
||||||
proc visibleTo*[T](thread: T, user: Option[User]): bool =
|
proc visibleTo*[T](thread: T, user: Option[User]): bool =
|
||||||
## Determines whether the specified thread (or post) should be
|
## Determines whether the specified thread (or post) should be
|
||||||
|
|
@ -147,11 +155,11 @@ when defined(js):
|
||||||
else:
|
else:
|
||||||
state.list = some(list)
|
state.list = some(list)
|
||||||
|
|
||||||
proc onLoadMore(ev: Event, n: VNode, categoryIdOption: Option[int]) =
|
proc onLoadMore(ev: Event, n: VNode, categoryId: Option[int]) =
|
||||||
state.loading = true
|
state.loading = true
|
||||||
let start = state.list.get().threads.len
|
let start = state.list.get().threads.len
|
||||||
if categoryIdOption.isSome:
|
if categoryId.isSome:
|
||||||
ajaxGet(makeUri("threads.json?start=" & $start & "&categoryId=" & $categoryIdOption.get()), @[], onThreadList)
|
ajaxGet(makeUri("threads.json?start=" & $start & "&categoryId=" & $categoryId.get()), @[], onThreadList)
|
||||||
else:
|
else:
|
||||||
ajaxGet(makeUri("threads.json?start=" & $start), @[], onThreadList)
|
ajaxGet(makeUri("threads.json?start=" & $start), @[], onThreadList)
|
||||||
|
|
||||||
|
|
@ -178,15 +186,15 @@ when defined(js):
|
||||||
isNew: thread.creation > previousVisitAt
|
isNew: thread.creation > previousVisitAt
|
||||||
)
|
)
|
||||||
|
|
||||||
proc genThreadList(currentUser: Option[User], categoryIdOption: Option[int]): VNode =
|
proc genThreadList(currentUser: Option[User], categoryId: Option[int]): VNode =
|
||||||
if state.status != Http200:
|
if state.status != Http200:
|
||||||
return renderError("Couldn't retrieve threads.", state.status)
|
return renderError("Couldn't retrieve threads.", state.status)
|
||||||
|
|
||||||
if state.list.isNone:
|
if state.list.isNone:
|
||||||
if not state.loading:
|
if not state.loading:
|
||||||
state.loading = true
|
state.loading = true
|
||||||
if categoryIdOption.isSome:
|
if categoryId.isSome:
|
||||||
ajaxGet(makeUri("threads.json?categoryId=" & $categoryIdOption.get()), @[], onThreadList)
|
ajaxGet(makeUri("threads.json?categoryId=" & $categoryId.get()), @[], onThreadList)
|
||||||
else:
|
else:
|
||||||
ajaxGet(makeUri("threads.json"), @[], onThreadList)
|
ajaxGet(makeUri("threads.json"), @[], onThreadList)
|
||||||
|
|
||||||
|
|
@ -229,10 +237,10 @@ when defined(js):
|
||||||
tdiv(class="loading loading-lg")
|
tdiv(class="loading loading-lg")
|
||||||
else:
|
else:
|
||||||
td(colspan="6",
|
td(colspan="6",
|
||||||
onClick = (ev: Event, n: VNode) => (onLoadMore(ev, n, categoryIdOption))):
|
onClick = (ev: Event, n: VNode) => (onLoadMore(ev, n, categoryId))):
|
||||||
span(text "load more threads")
|
span(text "load more threads")
|
||||||
|
|
||||||
proc renderThreadList*(currentUser: Option[User], categoryIdOption = none(int)): VNode =
|
proc renderThreadList*(currentUser: Option[User], categoryId = none(int)): VNode =
|
||||||
result = buildHtml(tdiv):
|
result = buildHtml(tdiv):
|
||||||
renderMainButtons(currentUser, categoryIdOption=categoryIdOption)
|
state.mainButtons.render(currentUser, categoryId=categoryId)
|
||||||
genThreadList(currentUser, categoryIdOption)
|
genThreadList(currentUser, categoryId)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue