The time a user was last online is now tracked and the main page displays the "online" users as well as some other stats.

This commit is contained in:
dom96 2012-05-16 16:38:23 +01:00
commit 753e946817
5 changed files with 126 additions and 8 deletions

11
editdb.nim Normal file
View file

@ -0,0 +1,11 @@
import strutils, db_sqlite
var db = Open(connection="nimforum.db", user="postgres", password="",
database="nimforum")
db.exec(sql"""ALTER TABLE person add column
lastOnline timestamp
""", [])
close(db)

View file

@ -186,4 +186,33 @@
# else:
<span style="color:red">You're already logged in!</span>
# end if
#end proc
#end proc
#
#
#proc genListOnline(c: var TForumData): string =
# result = ""
# let stats = c.getStats()
<div id="whoisonline">
<div class="wioHeader">
<span>Who is online?<span>
</div>
<div class="content">
<span>Out of ${stats.totalUsers} users ${stats.activeUsers.len} are online:
#for index, usr in stats.activeUsers:
# if usr.isAdmin:
#if index != 0: result.add ','
#end if
<span class="user admin">${usr.nick}</span>
# else:
#if index != 0: result.add ','
#end if
<span class="user">${usr.nick}</span>
# end if
#end for
</span>
<hr/>
<span>Total threads: ${stats.totalThreads} | Total posts: ${stats.totalPosts} | Newest member: ${stats.newestMember.nick}</span>
</div>
</div>
#end proc

View file

@ -37,6 +37,13 @@ type
TStyledButton = tuple[text: string, link: string]
TForumStats = object
totalUsers: int
totalPosts: int
totalThreads: int
newestMember: tuple[nick: string, id: int, isAdmin: bool]
activeUsers: seq[tuple[nick: string, id: int, isAdmin: bool]]
var
db: TDbConn
docConfig: PStringTable
@ -211,8 +218,8 @@ proc register(c: var TForumData, name, pass, antibot, email: string): bool =
# perform registration:
var salt = makeSalt()
Exec(db, sql("INSERT INTO person(name, password, email, salt, status) " &
"VALUES (?, ?, ?, ?, 'user')"), name,
Exec(db, sql("INSERT INTO person(name, password, email, salt, status, lastOnline) " &
"VALUES (?, ?, ?, ?, 'user', DATETIME('now'))"), name,
makePassword(pass, salt), email, salt)
# return setError(c, "", "Could not create your account!")
return true
@ -234,6 +241,10 @@ proc checkLoggedIn(c: var TForumData) =
c.username = ||row[0]
c.email = ||row[1]
c.isAdmin = parseBool(||row[2])
# Update lastOnline
db.exec(sql"update person set lastOnline = DATETIME('now') where id = ?",
c.userid)
else:
echo("SID not found in sessions. Assuming logged out.")
@ -405,6 +416,29 @@ proc genActionMenu(c: var TForumData): string =
btns.add(("New Thread", c.req.makeUri("/newthread", false)))
result = c.genButtons(btns)
proc getStats(c: var TForumData): TForumStats =
const totalUsersQuery =
sql"select count(*) from person"
result.totalUsers = getValue(db, totalUsersQuery).parseInt
const totalPostsQuery =
sql"select count(*) from post"
result.totalPosts = getValue(db, totalPostsQuery).parseInt
const totalThreadsQuery =
sql"select count(*) from thread"
result.totalThreads = getValue(db, totalThreadsQuery).parseInt
var newestMemberCreation = 0
result.activeUsers = @[]
const getUsersQuery =
sql"select id, name, admin, strftime('%s', lastOnline), strftime('%s', creation) from person"
for row in fastRows(db, getUsersQuery):
let lastOnlineSeconds = getTime() - TTime(row[3].parseInt)
if lastOnlineSeconds < (60 * 5): # 5 minutes
result.activeUsers.add((row[1], row[0].parseInt, row[2].parseBool))
if row[4].parseInt > newestMemberCreation:
result.newestMember = (row[1], row[0].parseInt, row[2].parseBool)
newestMemberCreation = row[4].parseInt
include "forms.tmpl"
include "main.tmpl"
@ -424,7 +458,7 @@ template createTFD(): stmt =
get "/":
createTFD()
resp genMain(c, genThreadsList(c))
resp genMain(c, genThreadsList(c), true)
get "/t/@threadid/?":
createTFD()
@ -541,6 +575,6 @@ when isMainModule:
if paramCount() > 0:
if paramStr(1) == "scgi":
http = false
run(websiteLoc, port = TPort(9001), http = http)
run(websiteLoc, port = TPort(9000), http = http)
db.close()

View file

@ -1,5 +1,5 @@
#! stdtmpl
#proc genMain(c: var TForumData, content: string): string =
#proc genMain(c: var TForumData, content: string, mainPage = false): string =
# result = ""
<!doctype html>
<html lang="en">
@ -38,9 +38,16 @@
<div id="topbar">
${c.genActionMenu}
</div>
#if mainPage:
${c.genListOnline}
#end if
</div>
<div id="footer">
<p>Written in Nimrod. Generated in ${int((epochTime()-c.startTime)*1000.0)}ms.</p>
<span>Written in <a href="http://nimrod-code.org/">Nimrod</a> using <a href="https://github.com/dom96/jester">Jester</a></span>
<span> | <a href="https://github.com/nimrod-code/nimforum">Fork on Github</a></span>
<span style="float:right;">Generated in ${int((epochTime()-c.startTime)*1000.0)}ms</span>
</div>
</body>
</html>

View file

@ -122,13 +122,50 @@ div#header a:hover, #nimbtn a:hover {
width: 15%;
}
#whoisonline {
margin: 5pt;
font-size: 9pt;
}
#whoisonline .wioHeader {
background-color: #5D5D5D;
background: -moz-linear-gradient(top, #5D5D5D, #4D4D4D);
background: -webkit-linear-gradient(top, #5D5D5D, #4d4d4d);
background: -o-linear-gradient(top, #5D5D5D, #4d4d4d);
color: #ffffff;
border-bottom: #2d2d2d solid 1px;
padding: 3px;
padding-left: 5pt;
}
#whoisonline .content {
border: #9d9d9d solid 1px;
border-top: #2D2D2D solid 1px;
padding: 5pt;
}
#whoisonline .content hr {
margin-top: 5pt;
margin-bottom: 5pt;
}
#footer {
background-color: #5D5D5D;
background: -moz-linear-gradient(top, #5D5D5D, #4D4D4D);
background: -webkit-linear-gradient(top, #5D5D5D, #4d4d4d);
background: -o-linear-gradient(top, #5D5D5D, #4d4d4d);
color: #ffffff;
text-align: center;
padding-left: 5px;
padding-right: 5px;
}
#footer a:link, #footer a:visited {
color: #ffffff;
}
#footer a:hover {
text-decoration: none;
}
#topbar {