mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 23:58:31 -05:00
A bunch of tweaks to the Users directory
- Move user directory from `/directory` to `/users/` - Defaults to 'weekly' time period - Don't include deleted topics/posts in the results - Move heart icon to header instead of on each row - "Users" instead of "Users found"
This commit is contained in:
parent
f807527650
commit
7ef306cd3b
19 changed files with 87 additions and 106 deletions
|
@ -7,6 +7,12 @@ export default Ember.Component.extend(StringBuffer, {
|
||||||
rerenderTriggers: ['order', 'asc'],
|
rerenderTriggers: ['order', 'asc'],
|
||||||
|
|
||||||
renderString(buffer) {
|
renderString(buffer) {
|
||||||
|
|
||||||
|
const icon = this.get('icon');
|
||||||
|
if (icon) {
|
||||||
|
buffer.push(iconHTML(icon));
|
||||||
|
}
|
||||||
|
|
||||||
const field = this.get('field');
|
const field = this.get('field');
|
||||||
buffer.push(I18n.t('directory.' + field));
|
buffer.push(I18n.t('directory.' + field));
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
queryParams: ['order', 'asc'],
|
queryParams: ['period', 'order', 'asc'],
|
||||||
|
period: 'weekly',
|
||||||
order: 'likes_received',
|
order: 'likes_received',
|
||||||
asc: null,
|
asc: null,
|
||||||
|
|
|
@ -11,10 +11,6 @@ export default function() {
|
||||||
});
|
});
|
||||||
this.resource('topicBySlug', { path: '/t/:slug' });
|
this.resource('topicBySlug', { path: '/t/:slug' });
|
||||||
|
|
||||||
this.resource('directory', function() {
|
|
||||||
this.route('show', {path: '/:period'});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.resource('discovery', { path: '/' }, function() {
|
this.resource('discovery', { path: '/' }, function() {
|
||||||
// top
|
// top
|
||||||
this.route('top');
|
this.route('top');
|
||||||
|
@ -56,6 +52,7 @@ export default function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// User routes
|
// User routes
|
||||||
|
this.resource('users');
|
||||||
this.resource('user', { path: '/users/:username' }, function() {
|
this.resource('user', { path: '/users/:username' }, function() {
|
||||||
this.resource('userActivity', { path: '/activity' }, function() {
|
this.resource('userActivity', { path: '/activity' }, function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
export default Discourse.Route.extend({
|
|
||||||
beforeModel: function() {
|
|
||||||
this.controllerFor('directory-show').setProperties({ sort: null, asc: null });
|
|
||||||
this.replaceWith('directory.show', 'all');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,31 +1,22 @@
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
queryParams: {
|
queryParams: {
|
||||||
|
period: { refreshModel: true },
|
||||||
order: { refreshModel: true },
|
order: { refreshModel: true },
|
||||||
asc: { refreshModel: true },
|
asc: { refreshModel: true },
|
||||||
},
|
},
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
// If we refresh via `refreshModel` set the old model to loading
|
// If we refresh via `refreshModel` set the old model to loading
|
||||||
const existing = this.modelFor('directory-show');
|
const existing = this.modelFor('users');
|
||||||
if (existing) {
|
if (existing) {
|
||||||
existing.set('loading', true);
|
existing.set('loading', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._period = params.period;
|
this._period = params.period;
|
||||||
return this.store.find('directoryItem', {
|
return this.store.find('directoryItem', params);
|
||||||
id: params.period,
|
|
||||||
asc: params.asc,
|
|
||||||
order: params.order
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
controller.setProperties({ model, period: this._period });
|
controller.setProperties({ model, period: this._period });
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
changePeriod(period) {
|
|
||||||
this.transitionTo('directory.show', period);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
|
@ -1,5 +0,0 @@
|
||||||
<div class="container">
|
|
||||||
<div class='directory'>
|
|
||||||
{{outlet}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,50 +0,0 @@
|
||||||
{{period-chooser period=period action="changePeriod"}}
|
|
||||||
|
|
||||||
{{#loading-spinner condition=model.loading}}
|
|
||||||
{{#if model.length}}
|
|
||||||
<span class='total-rows'>{{i18n "directory.total_rows" count=model.totalRows}}</span>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<th> </th>
|
|
||||||
{{directory-toggle field="likes_received" order=order asc=asc}}
|
|
||||||
{{directory-toggle field="likes_given" order=order asc=asc}}
|
|
||||||
{{directory-toggle field="topic_count" order=order asc=asc}}
|
|
||||||
{{directory-toggle field="post_count" order=order asc=asc}}
|
|
||||||
{{directory-toggle field="topics_entered" order=order asc=asc}}
|
|
||||||
{{#if showTimeRead}}
|
|
||||||
<th>{{i18n "directory.time_read"}}</th>
|
|
||||||
{{/if}}
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{#each item in model}}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{avatar item imageSize="tiny"}}
|
|
||||||
{{#link-to 'user' item.username}}{{unbound item.username}}{{/link-to}}
|
|
||||||
</td>
|
|
||||||
<td class="likes">
|
|
||||||
{{fa-icon "heart"}}
|
|
||||||
{{number item.likes_received}}
|
|
||||||
</td>
|
|
||||||
<td class="likes">
|
|
||||||
{{fa-icon "heart"}}
|
|
||||||
{{number item.likes_given}}
|
|
||||||
</td>
|
|
||||||
<td>{{number item.topic_count}}</td>
|
|
||||||
<td>{{number item.post_count}}</td>
|
|
||||||
<td>{{number item.topics_entered}}</td>
|
|
||||||
{{#if showTimeRead}}
|
|
||||||
<td>{{unbound item.time_read}}</td>
|
|
||||||
{{/if}}
|
|
||||||
</tr>
|
|
||||||
{{/each}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{{loading-spinner condition=model.loadingMore}}
|
|
||||||
{{else}}
|
|
||||||
<div class='clearfix'></div>
|
|
||||||
<p>{{i18n "directory.no_results"}}</p>
|
|
||||||
{{/if}}
|
|
||||||
{{/loading-spinner}}
|
|
|
@ -22,7 +22,7 @@
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<li>{{#link-to 'directory'}}{{i18n "directory.title"}}{{/link-to}}</li>
|
<li>{{#link-to 'users'}}{{i18n "directory.title"}}{{/link-to}}</li>
|
||||||
|
|
||||||
{{plugin-outlet "site-map-links"}}
|
{{plugin-outlet "site-map-links"}}
|
||||||
|
|
||||||
|
|
50
app/assets/javascripts/discourse/templates/users.hbs
Normal file
50
app/assets/javascripts/discourse/templates/users.hbs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<div class="container">
|
||||||
|
<div class='directory'>
|
||||||
|
|
||||||
|
{{period-chooser period=period}}
|
||||||
|
|
||||||
|
{{#loading-spinner condition=model.loading}}
|
||||||
|
{{#if model.length}}
|
||||||
|
<span class='total-rows'>{{i18n "directory.total_rows" count=model.totalRows}}</span>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<th> </th>
|
||||||
|
{{directory-toggle field="likes_received" order=order asc=asc icon="heart"}}
|
||||||
|
{{directory-toggle field="likes_given" order=order asc=asc icon="heart"}}
|
||||||
|
{{directory-toggle field="topic_count" order=order asc=asc}}
|
||||||
|
{{directory-toggle field="post_count" order=order asc=asc}}
|
||||||
|
{{directory-toggle field="topics_entered" order=order asc=asc}}
|
||||||
|
{{#if showTimeRead}}
|
||||||
|
<th>{{i18n "directory.time_read"}}</th>
|
||||||
|
{{/if}}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each item in model}}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{avatar item imageSize="tiny"}}
|
||||||
|
{{#link-to 'user' item.username}}{{unbound item.username}}{{/link-to}}
|
||||||
|
</td>
|
||||||
|
<td>{{number item.likes_received}}</td>
|
||||||
|
<td>{{number item.likes_given}}</td>
|
||||||
|
<td>{{number item.topic_count}}</td>
|
||||||
|
<td>{{number item.post_count}}</td>
|
||||||
|
<td>{{number item.topics_entered}}</td>
|
||||||
|
{{#if showTimeRead}}
|
||||||
|
<td>{{unbound item.time_read}}</td>
|
||||||
|
{{/if}}
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{{loading-spinner condition=model.loadingMore}}
|
||||||
|
{{else}}
|
||||||
|
<div class='clearfix'></div>
|
||||||
|
<p>{{i18n "directory.no_results"}}</p>
|
||||||
|
{{/if}}
|
||||||
|
{{/loading-spinner}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -26,9 +26,14 @@
|
||||||
|
|
||||||
th.sortable {
|
th.sortable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
width: 13%;
|
width: 13%;
|
||||||
i.fa {
|
i.fa-heart {
|
||||||
|
color: $love;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
i.fa-chevron-down, i.fa-chevron-up {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +41,5 @@
|
||||||
background-color: scale-color-diff();
|
background-color: scale-color-diff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td.likes {
|
|
||||||
i {
|
|
||||||
color: $love;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
class DirectoryController < ApplicationController
|
|
||||||
# This controller just exists to avoid 404s and to have the ember app load up
|
|
||||||
def index
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,8 +2,8 @@ class DirectoryItemsController < ApplicationController
|
||||||
PAGE_SIZE = 50
|
PAGE_SIZE = 50
|
||||||
|
|
||||||
def index
|
def index
|
||||||
id = params.require(:id)
|
period = params.require(:period)
|
||||||
period_type = DirectoryItem.period_types[id.to_sym]
|
period_type = DirectoryItem.period_types[period.to_sym]
|
||||||
raise Discourse::InvalidAccess.new(:period_type) unless period_type
|
raise Discourse::InvalidAccess.new(:period_type) unless period_type
|
||||||
|
|
||||||
result = DirectoryItem.where(period_type: period_type).includes(:user)
|
result = DirectoryItem.where(period_type: period_type).includes(:user)
|
||||||
|
@ -24,7 +24,7 @@ class DirectoryItemsController < ApplicationController
|
||||||
|
|
||||||
serialized = serialize_data(result, DirectoryItemSerializer)
|
serialized = serialize_data(result, DirectoryItemSerializer)
|
||||||
|
|
||||||
more_params = params.slice(:id, :order, :asc)
|
more_params = params.slice(:period, :order, :asc)
|
||||||
more_params[:page] = page + 1
|
more_params[:page] = page + 1
|
||||||
|
|
||||||
render_json_dump directory_items: serialized,
|
render_json_dump directory_items: serialized,
|
||||||
|
|
|
@ -25,6 +25,9 @@ class UsersController < ApplicationController
|
||||||
:authorize_email,
|
:authorize_email,
|
||||||
:password_reset]
|
:password_reset]
|
||||||
|
|
||||||
|
def index
|
||||||
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@user = fetch_user_from_params
|
@user = fetch_user_from_params
|
||||||
user_serializer = UserSerializer.new(@user, scope: guardian, root: 'user')
|
user_serializer = UserSerializer.new(@user, scope: guardian, root: 'user')
|
||||||
|
|
|
@ -42,9 +42,13 @@ class DirectoryItem < ActiveRecord::Base
|
||||||
SUM(CASE WHEN ua.action_type = :reply_type THEN 1 ELSE 0 END)
|
SUM(CASE WHEN ua.action_type = :reply_type THEN 1 ELSE 0 END)
|
||||||
FROM users AS u
|
FROM users AS u
|
||||||
LEFT OUTER JOIN user_actions AS ua ON ua.user_id = u.id
|
LEFT OUTER JOIN user_actions AS ua ON ua.user_id = u.id
|
||||||
|
LEFT OUTER JOIN topics AS t ON ua.target_topic_id = t.id
|
||||||
|
LEFT OUTER JOIN posts AS p ON ua.target_post_id = p.id
|
||||||
WHERE u.active
|
WHERE u.active
|
||||||
AND NOT u.blocked
|
AND NOT u.blocked
|
||||||
AND COALESCE(ua.created_at, :since) >= :since
|
AND COALESCE(ua.created_at, :since) >= :since
|
||||||
|
AND t.deleted_at IS NULL
|
||||||
|
AND p.deleted_at IS NULL
|
||||||
AND u.id > 0
|
AND u.id > 0
|
||||||
GROUP BY u.id",
|
GROUP BY u.id",
|
||||||
period_type: period_types[period_type],
|
period_type: period_types[period_type],
|
||||||
|
|
|
@ -247,8 +247,8 @@ en:
|
||||||
post_count: "Replies"
|
post_count: "Replies"
|
||||||
no_results: "No results were found for this time period."
|
no_results: "No results were found for this time period."
|
||||||
total_rows:
|
total_rows:
|
||||||
one: "1 user found"
|
one: "1 user"
|
||||||
other: "%{count} users found"
|
other: "%{count} users"
|
||||||
|
|
||||||
groups:
|
groups:
|
||||||
visible: "Group is visible to all users"
|
visible: "Group is visible to all users"
|
||||||
|
|
|
@ -25,7 +25,6 @@ Discourse::Application.routes.draw do
|
||||||
|
|
||||||
resources :about
|
resources :about
|
||||||
|
|
||||||
resources :directory
|
|
||||||
resources :directory_items
|
resources :directory_items
|
||||||
|
|
||||||
get "site" => "site#site"
|
get "site" => "site#site"
|
||||||
|
|
|
@ -2,12 +2,12 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe DirectoryItemsController do
|
describe DirectoryItemsController do
|
||||||
|
|
||||||
it "requires an `id` param" do
|
it "requires a `period` param" do
|
||||||
->{ xhr :get, :index }.should raise_error
|
->{ xhr :get, :index }.should raise_error
|
||||||
end
|
end
|
||||||
|
|
||||||
it "requires a proper `id` param" do
|
it "requires a proper `period` param" do
|
||||||
xhr :get, :index, id: 'eviltrout'
|
xhr :get, :index, period: 'eviltrout'
|
||||||
response.should_not be_success
|
response.should_not be_success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ describe DirectoryItemsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "succeeds with a valid value" do
|
it "succeeds with a valid value" do
|
||||||
xhr :get, :index, id: 'all'
|
xhr :get, :index, period: 'all'
|
||||||
response.should be_success
|
response.should be_success
|
||||||
json = ::JSON.parse(response.body)
|
json = ::JSON.parse(response.body)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
integration("User Directory");
|
integration("User Directory");
|
||||||
|
|
||||||
test("Visit Page", () => {
|
test("Visit Page", function() {
|
||||||
visit("/directory/all");
|
visit("/users");
|
||||||
andThen(() => {
|
andThen(() => {
|
||||||
ok(exists('.directory table tr'), "has a list of users");
|
ok(exists('.directory table tr'), "has a list of users");
|
||||||
});
|
});
|
Loading…
Reference in a new issue