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:
parent
5e79d2191b
commit
753e946817
5 changed files with 126 additions and 8 deletions
11
editdb.nim
Normal file
11
editdb.nim
Normal 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)
|
||||
31
forms.tmpl
31
forms.tmpl
|
|
@ -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
|
||||
|
|
|
|||
42
forum.nim
42
forum.nim
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
11
main.tmpl
11
main.tmpl
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue