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:
Robin Ward 2015-03-19 11:48:16 -04:00
parent f807527650
commit 7ef306cd3b
19 changed files with 87 additions and 106 deletions

View file

@ -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));

View file

@ -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,

View file

@ -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;

View file

@ -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');
}
});

View file

@ -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);
}
} }
}); });

View file

@ -1,5 +0,0 @@
<div class="container">
<div class='directory'>
{{outlet}}
</div>
</div>

View file

@ -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>&nbsp;</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}}

View file

@ -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"}}

View 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>&nbsp;</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>

View file

@ -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;
}
}
} }
} }

View file

@ -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

View file

@ -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,

View file

@ -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')

View file

@ -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],

View file

@ -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"

View file

@ -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"

View file

@ -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)

View file

@ -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");
}); });