Add frontend category picker and enable categories in threadlist
This commit is contained in:
parent
7e42479228
commit
7cda14e9fe
4 changed files with 113 additions and 10 deletions
|
|
@ -206,6 +206,14 @@ $threads-meta-color: #545d70;
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.square {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 0.3rem solid #98c766;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.load-more-separator {
|
||||
text-align: center;
|
||||
color: darken($label-color, 35%);
|
||||
|
|
@ -711,10 +719,8 @@ hr {
|
|||
|
||||
#threads-list.table {
|
||||
tr > th:nth-child(2), tr > td:nth-child(2) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.category, div.flag-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ type
|
|||
description*: string
|
||||
color*: string
|
||||
|
||||
CategoryList* = ref object
|
||||
categories*: seq[Category]
|
||||
|
||||
when defined(js):
|
||||
include karax/prelude
|
||||
|
|
@ -17,12 +19,13 @@ when defined(js):
|
|||
result = buildHtml():
|
||||
if category.name.len >= 0:
|
||||
tdiv(class="category",
|
||||
title=category.description,
|
||||
"data-color"="#" & category.color):
|
||||
tdiv(class="triangle",
|
||||
tdiv(class="square",
|
||||
style=style(
|
||||
(StyleAttr.borderBottom,
|
||||
kstring"0.6rem solid #" & category.color)
|
||||
(StyleAttr.border,
|
||||
kstring"0.3rem solid #" & category.color)
|
||||
))
|
||||
text category.name
|
||||
else:
|
||||
span()
|
||||
span()
|
||||
|
|
|
|||
88
src/frontend/categorypicker.nim
Normal file
88
src/frontend/categorypicker.nim
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
when defined(js):
|
||||
import sugar, httpcore, options, json
|
||||
import dom except Event
|
||||
|
||||
include karax/prelude
|
||||
import karax / [kajax, kdom, vstyles, vdom]
|
||||
|
||||
import error, replybox, threadlist, post, category
|
||||
import category, karaxutils
|
||||
|
||||
type
|
||||
CategoryPicker* = ref object of VComponent
|
||||
list: Option[CategoryList]
|
||||
selectedCategoryID*: int
|
||||
loading: bool
|
||||
status: HttpCode
|
||||
|
||||
proc getSelectedCategory*(state: CategoryPicker): Option[Category] =
|
||||
if state.list.isSome:
|
||||
return some(state.list.get().categories[state.selectedCategoryID])
|
||||
return none[Category]()
|
||||
|
||||
proc onCategoryList(state: CategoryPicker): proc (httpStatus: int, response: kstring) =
|
||||
return proc (httpStatus: int, response: kstring) =
|
||||
state.loading = false
|
||||
state.status = httpStatus.HttpCode
|
||||
if state.status != Http200: return
|
||||
|
||||
let parsed = parseJson($response)
|
||||
let list = parsed.to(CategoryList)
|
||||
|
||||
if state.list.isSome:
|
||||
state.list.get().categories.add(list.categories)
|
||||
else:
|
||||
state.list = some(list)
|
||||
|
||||
if state.selectedCategoryID > state.list.get().categories.len():
|
||||
state.selectedCategoryID = 0
|
||||
|
||||
proc loadCategories(state: CategoryPicker) =
|
||||
if not state.loading:
|
||||
state.loading = true
|
||||
ajaxGet(makeUri("categories.json"), @[], onCategoryList(state))
|
||||
|
||||
proc newCategoryPicker*(): CategoryPicker =
|
||||
result = CategoryPicker(
|
||||
list: none[CategoryList](),
|
||||
selectedCategoryID: 0,
|
||||
loading: false,
|
||||
status: Http200
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
proc render*(state: CategoryPicker): VNode =
|
||||
if state.status != Http200:
|
||||
return renderError("Couldn't retrieve categories.", state.status)
|
||||
|
||||
if state.list.isNone:
|
||||
state.loadCategories()
|
||||
return buildHtml(tdiv(class="loading loading-lg"))
|
||||
|
||||
let list = state.list.get().categories
|
||||
let selectedCategory = list[state.selectedCategoryID]
|
||||
|
||||
result = buildHtml():
|
||||
tdiv(id="category-selection", class="input-group"):
|
||||
label(class="d-inline-block form-label"):
|
||||
text "Category"
|
||||
tdiv(class="dropdown"):
|
||||
a(class="btn btn-link dropdown-toggle", tabindex="0"):
|
||||
tdiv(class="d-inline-block"):
|
||||
render(selectedCategory)
|
||||
text " "
|
||||
italic(class="fas fa-caret-down")
|
||||
ul(class="menu"):
|
||||
for category in list:
|
||||
li(class="menu-item"):
|
||||
a(onClick=onCategoryClick(state, category)):
|
||||
render(category)
|
||||
|
||||
|
||||
|
||||
|
|
@ -5,8 +5,8 @@ when defined(js):
|
|||
include karax/prelude
|
||||
import karax / [kajax, kdom]
|
||||
|
||||
import error, replybox, threadlist, post
|
||||
import karaxutils
|
||||
import error, replybox, threadlist, post, category
|
||||
import karaxutils, categorypicker
|
||||
|
||||
type
|
||||
NewThread* = ref object
|
||||
|
|
@ -14,11 +14,13 @@ when defined(js):
|
|||
error: Option[PostError]
|
||||
replyBox: ReplyBox
|
||||
subject: kstring
|
||||
categoryPicker: CategoryPicker
|
||||
|
||||
proc newNewThread*(): NewThread =
|
||||
NewThread(
|
||||
replyBox: newReplyBox(nil),
|
||||
subject: ""
|
||||
subject: "",
|
||||
categoryPicker: newCategoryPicker()
|
||||
)
|
||||
|
||||
proc onSubjectChange(e: Event, n: VNode, state: NewThread) =
|
||||
|
|
@ -37,8 +39,11 @@ when defined(js):
|
|||
let uri = makeUri("newthread")
|
||||
# TODO: This is a hack, karax should support this.
|
||||
let formData = newFormData()
|
||||
let categoryID = state.categoryPicker.selectedCategoryID
|
||||
|
||||
formData.append("subject", state.subject)
|
||||
formData.append("msg", state.replyBox.getText())
|
||||
formData.append("categoryId", $categoryID)
|
||||
ajaxPost(uri, @[], cast[cstring](formData),
|
||||
(s: int, r: kstring) => onCreatePost(s, r, state))
|
||||
|
||||
|
|
@ -55,6 +60,7 @@ when defined(js):
|
|||
if state.error.isSome():
|
||||
p(class="text-error"):
|
||||
text state.error.get().message
|
||||
render(state.categoryPicker)
|
||||
renderContent(state.replyBox, none[Thread](), none[Post]())
|
||||
tdiv(class="footer"):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue