Implements simple stats in profile view.

This commit is contained in:
Dominik Picheta 2018-05-15 14:14:37 +01:00
commit 2dd9dd52a2
4 changed files with 135 additions and 10 deletions

View file

@ -1015,10 +1015,10 @@ template createTFD() =
#[ 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(
name: userRow[0],
avatarUrl: userRow[1].getGravatarUrl(),
avatarUrl: userRow[1].getGravatarUrl(avatarSize),
lastOnline: userRow[2].parseInt,
rank: parseEnum[Rank](userRow[3])
)
@ -1216,7 +1216,8 @@ routes:
let postsQuery = sql("""
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
where u.id = p.author and u.name = ?
order by p.id desc;
@ -1230,7 +1231,8 @@ routes:
let rows = db.getAllRows(postsQuery, username)
profile.user = selectUser(@[
rows[0][4], rows[0][5], rows[0][6], rows[0][7]
])
], avatarSize=200)
profile.joinTime = rows[0][8].parseInt()
if c.rank >= Admin:
profile.email = some(rows[0][5])

View file

@ -4,16 +4,18 @@ from dom import window, Location
include karax/prelude
import jester/patterns
import threadlist, postlist, header
import threadlist, postlist, header, profile
import karaxutils
type
State = ref object
url: Location
profile: ProfileState
proc newState(): State =
State(
url: window.location
url: window.location,
profile: newProfileState()
)
var state = newState()
@ -44,7 +46,11 @@ proc render(): VNode =
result = buildHtml(tdiv()):
renderHeader()
route([
r("/t/@id?",
r("/profile/@username",
(params: Params) =>
(render(state.profile, params["username"]))
),
r("/t/@id",
(params: Params) =>
(renderPostList(params["id"].parseInt(), isLoggedIn()))
),

View file

@ -449,4 +449,54 @@ hr {
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;
}
}

View file

@ -1,5 +1,6 @@
import options
import threadlist, post
import options, httpcore, json, sugar
import threadlist, post, category, error
type
Profile* = object
user*: User
@ -9,3 +10,69 @@ type
# Information that only admins should see.
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")