Add frontend for category picker when admin or thread author
This commit is contained in:
parent
b0639c4da2
commit
cb7418f825
2 changed files with 61 additions and 6 deletions
|
|
@ -14,6 +14,7 @@ when defined(js):
|
|||
selectedCategoryID*: int
|
||||
loading: bool
|
||||
status: HttpCode
|
||||
onCategoryChange: proc (oldCategory: Category, newCategory: Category)
|
||||
|
||||
proc slug(name: string): string =
|
||||
name.strip().replace(" ", "-").toLowerAscii
|
||||
|
|
@ -40,20 +41,32 @@ when defined(js):
|
|||
state.loading = true
|
||||
ajaxGet(makeUri("categories.json"), @[], onCategoryList(state))
|
||||
|
||||
proc newCategoryPicker*(): CategoryPicker =
|
||||
proc `[]`*(state: CategoryPicker, id: int): Category =
|
||||
state.list.get().categories[id]
|
||||
|
||||
proc newCategoryPicker*(
|
||||
onCategoryChange: proc (oldCategory: Category, newCategory: Category) =
|
||||
proc (oldCategory: Category, newCategory: Category) = discard
|
||||
): CategoryPicker =
|
||||
result = CategoryPicker(
|
||||
list: none[CategoryList](),
|
||||
selectedCategoryID: 0,
|
||||
loading: false,
|
||||
status: Http200
|
||||
status: Http200,
|
||||
onCategoryChange: onCategoryChange
|
||||
)
|
||||
|
||||
proc select*(state: CategoryPicker, id: int) =
|
||||
state.selectedCategoryID = id
|
||||
state.markDirty()
|
||||
|
||||
proc onCategoryClick(state: CategoryPicker, category: Category): proc (ev: Event, n: VNode) =
|
||||
# this is necessary to capture the right value
|
||||
let cat = category
|
||||
return proc (ev: Event, n: VNode) =
|
||||
state.selectedCategoryID = cat.id
|
||||
state.markDirty()
|
||||
let oldCategory = state[state.selectedCategoryID]
|
||||
state.select(cat.id)
|
||||
state.onCategoryChange(oldCategory, cat)
|
||||
|
||||
proc render*(state: CategoryPicker): VNode =
|
||||
if state.status != Http200:
|
||||
|
|
|
|||
|
|
@ -20,12 +20,14 @@ when defined(js):
|
|||
import karax / [vstyles, kajax, kdom]
|
||||
|
||||
import karaxutils, error, replybox, editbox, postbutton, delete
|
||||
import categorypicker
|
||||
|
||||
type
|
||||
State = ref object
|
||||
list: Option[PostList]
|
||||
loading: bool
|
||||
status: HttpCode
|
||||
error: Option[PostError]
|
||||
replyingTo: Option[Post]
|
||||
replyBox: ReplyBox
|
||||
editing: Option[Post] ## If in edit mode, this contains the post.
|
||||
|
|
@ -33,8 +35,10 @@ when defined(js):
|
|||
likeButton: LikeButton
|
||||
deleteModal: DeleteModal
|
||||
lockButton: LockButton
|
||||
categoryPicker: CategoryPicker
|
||||
|
||||
proc onReplyPosted(id: int)
|
||||
proc onCategoryChanged(oldCategory: Category, newCategory: Category)
|
||||
proc onEditPosted(id: int, content: string, subject: Option[string])
|
||||
proc onEditCancelled()
|
||||
proc onDeletePost(post: Post)
|
||||
|
|
@ -44,17 +48,37 @@ when defined(js):
|
|||
list: none[PostList](),
|
||||
loading: false,
|
||||
status: Http200,
|
||||
error: none[PostError](),
|
||||
replyingTo: none[Post](),
|
||||
replyBox: newReplyBox(onReplyPosted),
|
||||
editBox: newEditBox(onEditPosted, onEditCancelled),
|
||||
likeButton: newLikeButton(),
|
||||
deleteModal: newDeleteModal(onDeletePost, onDeleteThread, nil),
|
||||
lockButton: newLockButton()
|
||||
lockButton: newLockButton(),
|
||||
categoryPicker: newCategoryPicker(onCategoryChanged)
|
||||
)
|
||||
|
||||
var
|
||||
state = newState()
|
||||
|
||||
proc onCategoryPost(httpStatus: int, response: kstring, state: State) =
|
||||
state.loading = false
|
||||
postFinished:
|
||||
discard
|
||||
# TODO: show success message
|
||||
|
||||
proc onCategoryChanged(oldCategory: Category, newCategory: Category) =
|
||||
let uri = makeUri("/updateThread")
|
||||
|
||||
let formData = newFormData()
|
||||
formData.append("threadId", $state.list.get().thread.id)
|
||||
formData.append("category", $newCategory.id)
|
||||
|
||||
state.loading = true
|
||||
|
||||
ajaxPost(uri, @[], cast[cstring](formData),
|
||||
(s: int, r: kstring) => onCategoryPost(s, r, state))
|
||||
|
||||
proc onPostList(httpStatus: int, response: kstring, postId: Option[int]) =
|
||||
state.loading = false
|
||||
state.status = httpStatus.HttpCode
|
||||
|
|
@ -66,6 +90,7 @@ when defined(js):
|
|||
state.list = some(list)
|
||||
|
||||
dom.document.title = list.thread.topic & " - " & dom.document.title
|
||||
state.categoryPicker.select(list.thread.category.id)
|
||||
|
||||
# The anchor should be jumped to once all the posts have been loaded.
|
||||
if postId.isSome():
|
||||
|
|
@ -179,6 +204,20 @@ when defined(js):
|
|||
span(class="more-post-count"):
|
||||
text "(" & $post.moreBefore.len & ")"
|
||||
|
||||
proc genCategories(thread: Thread, currentUser: Option[User]): VNode =
|
||||
let loggedIn = currentUser.isSome()
|
||||
let authoredByUser =
|
||||
loggedIn and currentUser.get().name == thread.author.name
|
||||
let currentAdmin =
|
||||
currentUser.isSome() and currentUser.get().rank == Admin
|
||||
|
||||
result = buildHtml():
|
||||
tdiv():
|
||||
if authoredByUser or currentAdmin:
|
||||
render(state.categoryPicker)
|
||||
else:
|
||||
render(thread.category)
|
||||
|
||||
proc genPostButtons(post: Post, currentUser: Option[User]): Vnode =
|
||||
let loggedIn = currentUser.isSome()
|
||||
let authoredByUser =
|
||||
|
|
@ -330,6 +369,9 @@ when defined(js):
|
|||
result = buildHtml():
|
||||
section(class="container grid-xl"):
|
||||
tdiv(id="thread-title", class="title"):
|
||||
if state.error.isSome():
|
||||
span(class="text-error"):
|
||||
text state.error.get().message
|
||||
p(): text list.thread.topic
|
||||
if list.thread.isLocked:
|
||||
italic(class="fas fa-lock fa-xs",
|
||||
|
|
@ -343,7 +385,7 @@ when defined(js):
|
|||
italic(class="fas fa-check-square fa-xs",
|
||||
title="Thread has a solution")
|
||||
text "Solved"
|
||||
render(list.thread.category)
|
||||
genCategories(list.thread, currentUser)
|
||||
tdiv(class="posts"):
|
||||
var prevPost: Option[Post] = none[Post]()
|
||||
for i, post in list.posts:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue