summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bucky/app/api.js7
-rw-r--r--bucky/app/bucky.js45
-rw-r--r--bucky/app/pages.js8
-rw-r--r--bucky/db/index.js11
-rw-r--r--public/assets/js/lib/router.js6
-rw-r--r--public/assets/js/lib/views/users/users.js55
-rw-r--r--views/pages/users.ejs67
7 files changed, 173 insertions, 26 deletions
diff --git a/bucky/app/api.js b/bucky/app/api.js
index 45dde3f..11ced51 100644
--- a/bucky/app/api.js
+++ b/bucky/app/api.js
@@ -37,9 +37,14 @@ function route (app){
app.get("/api/users",
middleware.ensureAuthenticated,
bucky.ensureUserlist,
+ bucky.ensureUserThreadCounts,
+ bucky.ensureUserFileCounts,
+ bucky.ensureUserCommentCounts,
+ bucky.ensureUserStatistics,
function(req, res) {
res.json({
- users: res.users
+ users: res.users,
+ userStats: res.userStats,
})
})
app.get("/api/profile/:username",
diff --git a/bucky/app/bucky.js b/bucky/app/bucky.js
index 8ff0b15..74caa66 100644
--- a/bucky/app/bucky.js
+++ b/bucky/app/bucky.js
@@ -579,6 +579,51 @@ var bucky = module.exports = {
next()
})
},
+ ensureUserThreadCounts: function (req, res, next) {
+ db.getUserThreadCounts().then(function(counts){
+ if (!counts) {
+ return res.sendStatus(404)
+ }
+ res.threadCounts = counts
+ next()
+ })
+ },
+ ensureUserCommentCounts: function (req, res, next) {
+ db.getUserCommentCounts().then(function(counts){
+ if (!counts) {
+ return res.sendStatus(404)
+ }
+ res.commentCounts = counts
+ next()
+ })
+ },
+ ensureUserFileCounts: function (req, res, next) {
+ db.getUserFileCounts().then(function(counts){
+ if (!counts) {
+ return res.sendStatus(404)
+ }
+ res.fileCounts = counts
+ next()
+ })
+ },
+ ensureUserStatistics: function (req, res, next) {
+ var stats = {}
+ res.threadCounts.forEach(function(user){
+ stats[user.username] = stats[user.username] || {}
+ stats[user.username].threads = user.count
+ })
+ res.commentCounts.forEach(function(user){
+ stats[user.username] = stats[user.username] || {}
+ stats[user.username].comments = user.count
+ })
+ res.fileCounts.forEach(function(user){
+ stats[user.username] = stats[user.username] || {}
+ stats[user.username].files = user.count
+ stats[user.username].fileSize = user.size
+ })
+ res.userStats = stats
+ next()
+ },
sanitizeUser: function(req, res, next) {
res.user = util.sanitizeUser(res.user)
next()
diff --git a/bucky/app/pages.js b/bucky/app/pages.js
index b007742..5d8551e 100644
--- a/bucky/app/pages.js
+++ b/bucky/app/pages.js
@@ -76,8 +76,12 @@ function route (app){
app.get("/users",
middleware.ensureAuthenticated,
function(req, res){
- res.render("pages/users", {
- })
+ res.render("pages/users", {})
+ })
+ app.get("/users/all",
+ middleware.ensureAuthenticated,
+ function(req, res){
+ res.render("pages/users", {})
})
app.get("/search/",
diff --git a/bucky/db/index.js b/bucky/db/index.js
index 53e36dd..312ca13 100644
--- a/bucky/db/index.js
+++ b/bucky/db/index.js
@@ -55,7 +55,7 @@ db.createUser = function(data){
}
db.getUsers = function () {
return User.query(function(qb){
- qb.orderBy("username", "desc")
+ qb.orderBy("username", "asc")
}).fetchAll({
columns: [
"id", "username", "realname", "firstseen", "lastseen",
@@ -148,6 +148,15 @@ db.getThreadUsers = function(thread_id){
db.getUserThreadIds = function(user_id){
return ThreadUser.query("where", "user_id", "=", user_id).fetch()
}
+db.getUserThreadCounts = function(ids){
+ return knex.column('username').count('* as count').select().from('threads').groupBy('username')
+}
+db.getUserCommentCounts = function(ids){
+ return knex.column('username').count('* as count').select().from('comments').groupBy('username')
+}
+db.getUserFileCounts = function(ids){
+ return knex.column('username').sum('size as size').count('* as count').select().from('files').groupBy('username')
+}
/* FILES */
diff --git a/public/assets/js/lib/router.js b/public/assets/js/lib/router.js
index f856283..ebdfa78 100644
--- a/public/assets/js/lib/router.js
+++ b/public/assets/js/lib/router.js
@@ -23,6 +23,7 @@ var SiteRouter = Router.extend({
"/mail/read/:id": 'message',
"/mail/reply/:id": 'compose',
"/users": 'users',
+ "/users/all": 'usersAll',
"/profile": 'profile',
"/profile/:username": 'profile',
"/profile/:username/edit": 'editProfile',
@@ -90,6 +91,11 @@ var SiteRouter = Router.extend({
app.view = new UsersView ()
app.view.load()
},
+
+ usersAll: function(username){
+ app.view = new UsersView ({ all: true })
+ app.view.load()
+ },
profile: function(username){
app.view = new ProfileView ()
diff --git a/public/assets/js/lib/views/users/users.js b/public/assets/js/lib/views/users/users.js
index cbb0fde..a45123d 100644
--- a/public/assets/js/lib/views/users/users.js
+++ b/public/assets/js/lib/views/users/users.js
@@ -1,6 +1,6 @@
var UsersView = View.extend({
- el: "#users_list",
+ el: "#user_list",
events: {
},
@@ -8,8 +8,15 @@ var UsersView = View.extend({
action: "/api/users",
initialize: function(opt){
+ opt = opt || {}
+ this.showAll = !!opt.all
this.template = this.$(".template").html()
this.form = new NewKeywordForm ({ parent: this })
+ if (!this.showAll) {
+ $('.all_link').attr('href', '/users/all').html('Show all users')
+ } else {
+ $('.all_link').attr('href', '/users').html('Show active users')
+ }
},
load: function(){
@@ -22,6 +29,8 @@ var UsersView = View.extend({
// data.threadGroups.forEach(kw => {
// keywordThreads[kw.keyword] = kw
// })
+ var showAll = this.showAll
+ var userStats = data.userStats
data.users
// .map(a => [parseInt((keywordThreads[a.keyword] || {})['sum(`viewed`)']) || 0, a])
// .sort((b,a) => cmp(a[0], b[0]))
@@ -34,31 +43,45 @@ var UsersView = View.extend({
// var threadCount = threadCountNum ? hush_threads(threadCountNum) : ['','']
// "id", "username", "realname", "firstseen", "lastseen",
// "location", "website", "avatar",
- var create_datetime = verbose_date(keyword.createdate)
- var age = get_age(thread.lastmodified)
- var id = thread.id + get_revision(thread)
+ console.log(user)
+ var stats = userStats[user.username] || {}
+ console.log(stats)
+ if (!showAll && !stats.threads && !stats.files && !stats.comments) {
+ return
+ }
+ var threadCount = stats.threads ? hush_threads(stats.threads) : ['','']
+ var fileCount = stats.files ? hush_null(stats.files, 'f') : ['','']
+ var commentCount = stats.comments ? hush_null(stats.comments, 'c') : ['','']
+ var firstseen_datetime = verbose_date(user.firstseen)
+ var lastseen = get_age(user.lastseen)
var t = this.template
- .replace(/{{keyword}}/g, sanitizeHTML(keyword.keyword))
- .replace(/{{id}}/g, id)
- .replace(/{{username}}/g, keyword.username)
- .replace(/{{title}}/g, thread.title)
- .replace(/{{create_date}}/g, create_datetime[0])
- .replace(/{{create_time}}/g, create_datetime[1])
- .replace(/{{date_class}}/g, carbon_date(thread.lastmodified) )
- .replace(/{{views}}/g, views[1])
+ .replace(/{{username}}/g, sanitizeHTML(user.username))
+ .replace(/{{id}}/g, user.id)
+ .replace(/{{realname}}/g, sanitizeHTML(user.realname))
+ .replace(/{{firstseen_date}}/g, firstseen_datetime[0])
+ .replace(/{{firstseen_time}}/g, firstseen_datetime[1])
+ .replace(/{{firstseen_date_class}}/g, carbon_date(user.firstseen) )
+ .replace(/{{lastseen}}/g, lastseen )
+ .replace(/{{lastseen_date_class}}/g, carbon_date(lastseen) )
.replace(/{{threadcount}}/, threadCount[1])
.replace(/{{threadcount_class}}/, threadCount[0])
+ .replace(/{{filecount}}/, fileCount[1])
+ .replace(/{{filecount_class}}/, fileCount[0])
+ .replace(/{{commentcount}}/, commentCount[1])
+ .replace(/{{commentcount_class}}/, commentCount[0])
// .replace(/{{comments}}/g, comments[1])
// .replace(/{{files}}/g, files[1])
// .replace(/{{size}}/g, size[1] )
- .replace(/{{views_class}}/g, views[0])
// .replace(/{{comments_class}}/g, comments[0])
// .replace(/{{files_class}}/g, files[0])
// .replace(/{{show_files}}/g, thread.file_count == 0 ? "hidden" : "")
// .replace(/{{size_class}}/g, size[0] )
- .replace(/{{color}}/g, thread.color || "blue" )
-
- this.$el.append(t)
+ // .replace(/{{color}}/g, thread.color || "blue" )
+ var $t = $(t)
+ if (!user.firstseen) {
+ $t.find('.date').html('')
+ }
+ this.$el.append($t)
})
$("body").removeClass('loading')
},
diff --git a/views/pages/users.ejs b/views/pages/users.ejs
index f18b254..3a3fdda 100644
--- a/views/pages/users.ejs
+++ b/views/pages/users.ejs
@@ -1,6 +1,8 @@
<% include ../partials/header %>
-<div class="subtitle"></div>
+<div class="subtitle">
+ <a class='all_link'></a>
+</div>
<div id="content">
<div id="user_list">
@@ -10,16 +12,22 @@
<div class='dot'>
&middot;
</div>
- <div class="date {{date_class}}">
- member since {{date}} <small>{{time}}</small>
+ <div class='realname'>
+ {{realname}}
+ </div>
+ <div class="date {{firstseen_date_class}}">
+ joined {{firstseen_date}} <small>{{firstseen_time}}</small>
</div>
- <div class="threadcount {{threadcount_class}}">
+ <div class="date {{lastseen_date_class}}">
+ seen {{lastseen}} ago
+ </div>
+ <div class="count {{threadcount_class}}">
{{threadcount}}
</div>
- <div class="filecount {{filecount_class}}">
+ <div class="count {{filecount_class}}">
{{filecount}}
</div>
- <div class="commentcount {{commentcount_class}}">
+ <div class="count {{commentcount_class}}">
{{commentcount}}
</div>
</div>
@@ -28,3 +36,50 @@
</div>
<% include ../partials/footer %>
+
+<style>
+.user_row {
+ display: flex;
+ flex-direction: row;
+ margin-top: 10px;
+}
+.user_row .username {
+ min-width: 70px;
+ justify-content: flex-end;
+ margin-right: 5px;
+}
+.user_row .realname {
+ min-width: 150px;
+}
+.user_row .date {
+ min-width: 160px;
+}
+.user_row div {
+ display: flex;
+}
+.user_row .dot {
+ margin-right: 5px;
+}
+.user_row .username a {
+ font-size: 12px;
+ font-weight: bold;
+ display: block;
+ min-width: 100px;
+ text-align: right;
+ margin-right: 5px;
+ margin-top: -3px;
+}
+.user_row .date small {
+ font-size: 9px;
+ margin-left: 3px;
+}
+.user_row .views {
+ min-width: 40px;
+ justify-content: center;
+}
+.user_row .count {
+ min-width: 40px;
+ justify-content: flex-end;
+ margin-right: 10px;
+}
+</style>