Implements simple stats in profile view.
This commit is contained in:
parent
d345bf76ae
commit
2dd9dd52a2
4 changed files with 135 additions and 10 deletions
10
forum.nim
10
forum.nim
|
|
@ -1015,10 +1015,10 @@ template createTFD() =
|
||||||
|
|
||||||
#[ DB functions. TODO: Move to another module? ]#
|
#[ DB functions. TODO: Move to another module? ]#
|
||||||
|
|
||||||
proc selectUser(userRow: seq[string]): threadlist.User =
|
proc selectUser(userRow: seq[string], avatarSize: int=80): threadlist.User =
|
||||||
return threadlist.User(
|
return threadlist.User(
|
||||||
name: userRow[0],
|
name: userRow[0],
|
||||||
avatarUrl: userRow[1].getGravatarUrl(),
|
avatarUrl: userRow[1].getGravatarUrl(avatarSize),
|
||||||
lastOnline: userRow[2].parseInt,
|
lastOnline: userRow[2].parseInt,
|
||||||
rank: parseEnum[Rank](userRow[3])
|
rank: parseEnum[Rank](userRow[3])
|
||||||
)
|
)
|
||||||
|
|
@ -1216,7 +1216,8 @@ routes:
|
||||||
|
|
||||||
let postsQuery = sql("""
|
let postsQuery = sql("""
|
||||||
select p.id, p.content, strftime('%s', p.creation), p.author,
|
select p.id, p.content, strftime('%s', p.creation), p.author,
|
||||||
u.name, u.email, strftime('%s', u.lastOnline), u.status
|
u.name, u.email, strftime('%s', u.lastOnline), u.status,
|
||||||
|
strftime('%s', u.creation)
|
||||||
from post p, person u
|
from post p, person u
|
||||||
where u.id = p.author and u.name = ?
|
where u.id = p.author and u.name = ?
|
||||||
order by p.id desc;
|
order by p.id desc;
|
||||||
|
|
@ -1230,7 +1231,8 @@ routes:
|
||||||
let rows = db.getAllRows(postsQuery, username)
|
let rows = db.getAllRows(postsQuery, username)
|
||||||
profile.user = selectUser(@[
|
profile.user = selectUser(@[
|
||||||
rows[0][4], rows[0][5], rows[0][6], rows[0][7]
|
rows[0][4], rows[0][5], rows[0][6], rows[0][7]
|
||||||
])
|
], avatarSize=200)
|
||||||
|
profile.joinTime = rows[0][8].parseInt()
|
||||||
|
|
||||||
if c.rank >= Admin:
|
if c.rank >= Admin:
|
||||||
profile.email = some(rows[0][5])
|
profile.email = some(rows[0][5])
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,18 @@ from dom import window, Location
|
||||||
include karax/prelude
|
include karax/prelude
|
||||||
import jester/patterns
|
import jester/patterns
|
||||||
|
|
||||||
import threadlist, postlist, header
|
import threadlist, postlist, header, profile
|
||||||
import karaxutils
|
import karaxutils
|
||||||
|
|
||||||
type
|
type
|
||||||
State = ref object
|
State = ref object
|
||||||
url: Location
|
url: Location
|
||||||
|
profile: ProfileState
|
||||||
|
|
||||||
proc newState(): State =
|
proc newState(): State =
|
||||||
State(
|
State(
|
||||||
url: window.location
|
url: window.location,
|
||||||
|
profile: newProfileState()
|
||||||
)
|
)
|
||||||
|
|
||||||
var state = newState()
|
var state = newState()
|
||||||
|
|
@ -44,7 +46,11 @@ proc render(): VNode =
|
||||||
result = buildHtml(tdiv()):
|
result = buildHtml(tdiv()):
|
||||||
renderHeader()
|
renderHeader()
|
||||||
route([
|
route([
|
||||||
r("/t/@id?",
|
r("/profile/@username",
|
||||||
|
(params: Params) =>
|
||||||
|
(render(state.profile, params["username"]))
|
||||||
|
),
|
||||||
|
r("/t/@id",
|
||||||
(params: Params) =>
|
(params: Params) =>
|
||||||
(renderPostList(params["id"].parseInt(), isLoggedIn()))
|
(renderPostList(params["id"].parseInt(), isLoggedIn()))
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -449,4 +449,54 @@ hr {
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "syntax.scss";
|
@import "syntax.scss";
|
||||||
|
|
||||||
|
// - Profile view
|
||||||
|
|
||||||
|
.profile {
|
||||||
|
@extend .tile;
|
||||||
|
margin-top: $control-padding-y*5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-icon {
|
||||||
|
@extend .tile-icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-avatar {
|
||||||
|
@extend .avatar;
|
||||||
|
@extend .avatar-xl;
|
||||||
|
|
||||||
|
height: 8.2rem;
|
||||||
|
width: 8.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-content {
|
||||||
|
@extend .tile-content;
|
||||||
|
padding: $control-padding-x $control-padding-y;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-title {
|
||||||
|
@extend .tile-title;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-stats {
|
||||||
|
dl {
|
||||||
|
border-top: 1px solid $border-color;
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: normal;
|
||||||
|
color: lighten($dark-color, 15%);
|
||||||
|
}
|
||||||
|
|
||||||
|
dt, dd {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
margin-right: $control-padding-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-right: $control-padding-x-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import options
|
import options, httpcore, json, sugar
|
||||||
import threadlist, post
|
|
||||||
|
import threadlist, post, category, error
|
||||||
type
|
type
|
||||||
Profile* = object
|
Profile* = object
|
||||||
user*: User
|
user*: User
|
||||||
|
|
@ -9,3 +10,69 @@ type
|
||||||
# Information that only admins should see.
|
# Information that only admins should see.
|
||||||
email*: Option[string]
|
email*: Option[string]
|
||||||
|
|
||||||
|
when defined(js):
|
||||||
|
include karax/prelude
|
||||||
|
import karax/[kajax]
|
||||||
|
import karaxutils
|
||||||
|
|
||||||
|
type
|
||||||
|
ProfileState* = ref object
|
||||||
|
profile: Option[Profile]
|
||||||
|
loading: bool
|
||||||
|
status: HttpCode
|
||||||
|
|
||||||
|
proc newProfileState*(): ProfileState =
|
||||||
|
ProfileState(
|
||||||
|
loading: false,
|
||||||
|
status: Http200
|
||||||
|
)
|
||||||
|
|
||||||
|
proc onProfile(httpStatus: int, response: kstring, state: ProfileState) =
|
||||||
|
# TODO: Try to abstract these.
|
||||||
|
state.loading = false
|
||||||
|
state.status = httpStatus.HttpCode
|
||||||
|
if state.status != Http200: return
|
||||||
|
|
||||||
|
let parsed = parseJson($response)
|
||||||
|
let profile = to(parsed, Profile)
|
||||||
|
|
||||||
|
state.profile = some(profile)
|
||||||
|
|
||||||
|
proc render*(state: ProfileState, username: string): VNode =
|
||||||
|
if state.status != Http200:
|
||||||
|
return renderError("Couldn't retrieve profile.")
|
||||||
|
|
||||||
|
if state.profile.isNone:
|
||||||
|
let uri = makeUri("profile.json", ("username", username))
|
||||||
|
ajaxGet(uri, @[], (s: int, r: kstring) => onProfile(s, r, state))
|
||||||
|
|
||||||
|
return buildHtml(tdiv(class="loading loading-lg"))
|
||||||
|
|
||||||
|
let profile = state.profile.get()
|
||||||
|
result = buildHtml():
|
||||||
|
section(class="container grid-xl"):
|
||||||
|
tdiv(class="profile"):
|
||||||
|
tdiv(class="profile-icon"):
|
||||||
|
render(profile.user, "profile-avatar")
|
||||||
|
tdiv(class="profile-content"):
|
||||||
|
h2(class="profile-title"):
|
||||||
|
text profile.user.name
|
||||||
|
|
||||||
|
tdiv(class="profile-stats"):
|
||||||
|
dl():
|
||||||
|
dt(text "Joined")
|
||||||
|
dd(text threadlist.renderActivity(profile.joinTime))
|
||||||
|
dt(text "Last Post")
|
||||||
|
dd(text renderActivity(profile.posts[0].info.creation))
|
||||||
|
dt(text "Last Online")
|
||||||
|
dd(text renderActivity(profile.user.lastOnline))
|
||||||
|
dt(text "Rank")
|
||||||
|
dd(text $profile.user.rank)
|
||||||
|
|
||||||
|
tdiv(class="columns"):
|
||||||
|
tdiv(class="column col-6"):
|
||||||
|
h4(text "Latest Posts")
|
||||||
|
tdiv(class="column col-6"):
|
||||||
|
h4(text "Latest Threads")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue