mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Refactor + Fix: Wasn't correctly loading activity streams. Code is a lot more Ember-y now.
This commit is contained in:
parent
89a617f0c6
commit
0f296cd42b
@ -177,23 +177,6 @@ Discourse.User = Discourse.Model.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
Filters out this user's stream of user actions by a given filter
|
|
||||||
|
|
||||||
@method filterStream
|
|
||||||
@param {String} filter
|
|
||||||
**/
|
|
||||||
filterStream: function(filter) {
|
|
||||||
if (Discourse.UserAction.statGroups[filter]) {
|
|
||||||
filter = Discourse.UserAction.statGroups[filter].join(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set('streamFilter', filter);
|
|
||||||
this.set('stream', Em.A());
|
|
||||||
this.set('totalItems', 0);
|
|
||||||
return this.loadMoreUserActions();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loads a single user action by id.
|
Loads a single user action by id.
|
||||||
|
|
||||||
@ -207,44 +190,9 @@ Discourse.User = Discourse.Model.extend({
|
|||||||
return Discourse.ajax("/user_actions/" + id + ".json", { cache: 'false' }).then(function(result) {
|
return Discourse.ajax("/user_actions/" + id + ".json", { cache: 'false' }).then(function(result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
if ((user.get('streamFilter') || result.action_type) !== result.action_type) return;
|
if ((user.get('streamFilter') || result.action_type) !== result.action_type) return;
|
||||||
|
var action = Discourse.UserAction.collapseStream([Discourse.UserAction.create(result)]);
|
||||||
var action = Em.A();
|
stream.set('itemsLoaded', user.get('itemsLoaded') + 1);
|
||||||
action.pushObject(Discourse.UserAction.create(result));
|
stream.insertAt(0, action[0]);
|
||||||
action = Discourse.UserAction.collapseStream(action);
|
|
||||||
|
|
||||||
user.set('totalItems', user.get('totalItems') + 1);
|
|
||||||
|
|
||||||
return stream.insertAt(0, action[0]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
Loads more user actions, and then calls a callback if defined.
|
|
||||||
|
|
||||||
@method loadMoreUserActions
|
|
||||||
@returns {Promise} the content of the user actions
|
|
||||||
**/
|
|
||||||
loadMoreUserActions: function() {
|
|
||||||
var user = this;
|
|
||||||
var stream = user.get('stream');
|
|
||||||
if (!stream) return;
|
|
||||||
|
|
||||||
var url = Discourse.getURL("/user_actions?offset=") + this.get('totalItems') + "&user_id=" + (this.get("id"));
|
|
||||||
if (this.get('streamFilter')) {
|
|
||||||
url += "&filter=" + (this.get('streamFilter'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Discourse.ajax(url, { cache: 'false' }).then( function(result) {
|
|
||||||
if (result && result.user_actions && result.user_actions.each) {
|
|
||||||
var copy = Em.A();
|
|
||||||
result.user_actions.each(function(i) {
|
|
||||||
return copy.pushObject(Discourse.UserAction.create(i));
|
|
||||||
});
|
|
||||||
copy = Discourse.UserAction.collapseStream(copy);
|
|
||||||
stream.pushObjects(copy);
|
|
||||||
user.set('stream', stream);
|
|
||||||
user.set('totalItems', user.get('totalItems') + result.user_actions.length);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -284,33 +232,36 @@ Discourse.User = Discourse.Model.extend({
|
|||||||
return this.get('stats').filterProperty('isPM');
|
return this.get('stats').filterProperty('isPM');
|
||||||
}.property('stats.@each.isPM'),
|
}.property('stats.@each.isPM'),
|
||||||
|
|
||||||
/**
|
|
||||||
Load extra details for the user
|
|
||||||
|
|
||||||
@method loadDetails
|
findDetails: function() {
|
||||||
**/
|
|
||||||
loadDetails: function() {
|
|
||||||
|
|
||||||
this.set('loading', true);
|
|
||||||
|
|
||||||
// Check the preload store first
|
|
||||||
var user = this;
|
var user = this;
|
||||||
var username = user.get('username');
|
return PreloadStore.getAndRemove("user_" + user.get('username'), function() {
|
||||||
|
return Discourse.ajax("/users/" + user.get('username') + '.json');
|
||||||
return PreloadStore.getAndRemove("user_" + username, function() {
|
|
||||||
return Discourse.ajax("/users/" + username + '.json');
|
|
||||||
}).then(function (json) {
|
}).then(function (json) {
|
||||||
|
|
||||||
// Create a user from the resulting JSON
|
|
||||||
json.user.stats = Discourse.User.groupStats(json.user.stats.map(function(s) {
|
json.user.stats = Discourse.User.groupStats(json.user.stats.map(function(s) {
|
||||||
if (s.count) s.count = parseInt(s.count, 10);
|
if (s.count) s.count = parseInt(s.count, 10);
|
||||||
return Discourse.UserActionStat.create(s);
|
return Discourse.UserActionStat.create(s);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
user.setProperties(json.user);
|
user.setProperties(json.user);
|
||||||
user.set('loading', false);
|
|
||||||
return user;
|
return user;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
findStream: function(filter) {
|
||||||
|
if (Discourse.UserAction.statGroups[filter]) {
|
||||||
|
filter = Discourse.UserAction.statGroups[filter].join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
var stream = Discourse.UserStream.create({
|
||||||
|
totalItems: 0,
|
||||||
|
content: [],
|
||||||
|
filter: filter,
|
||||||
|
user: this
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.findItems();
|
||||||
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
39
app/assets/javascripts/discourse/models/user_stream.js
Normal file
39
app/assets/javascripts/discourse/models/user_stream.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
Represents a user's stream
|
||||||
|
|
||||||
|
@class UserStream
|
||||||
|
@extends Discourse.Model
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.UserStream = Discourse.Model.extend({
|
||||||
|
|
||||||
|
filterChanged: function() {
|
||||||
|
this.setProperties({
|
||||||
|
content: Em.A(),
|
||||||
|
itemsLoaded: 0
|
||||||
|
});
|
||||||
|
this.findItems();
|
||||||
|
}.observes('filter'),
|
||||||
|
|
||||||
|
findItems: function() {
|
||||||
|
var url = Discourse.getURL("/user_actions?offset=") + this.get('itemsLoaded') + "&username=" + (this.get('user.username_lower'));
|
||||||
|
if (this.get('filter')) {
|
||||||
|
url += "&filter=" + (this.get('filter'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var stream = this;
|
||||||
|
return Discourse.ajax(url, {cache: 'false'}).then( function(result) {
|
||||||
|
if (result && result.user_actions && result.user_actions.each) {
|
||||||
|
var copy = Em.A();
|
||||||
|
result.user_actions.each(function(i) {
|
||||||
|
return copy.pushObject(Discourse.UserAction.create(i));
|
||||||
|
});
|
||||||
|
copy = Discourse.UserAction.collapseStream(copy);
|
||||||
|
stream.get('content').pushObjects(copy);
|
||||||
|
stream.set('itemsLoaded', stream.get('itemsLoaded') + result.user_actions.length);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
@ -11,9 +11,11 @@ Discourse.Route = Em.Route.extend({
|
|||||||
/**
|
/**
|
||||||
Called every time we enter a route on Discourse.
|
Called every time we enter a route on Discourse.
|
||||||
|
|
||||||
@method enter
|
@method activate
|
||||||
**/
|
**/
|
||||||
enter: function(router, context) {
|
activate: function(router, context) {
|
||||||
|
this._super();
|
||||||
|
|
||||||
// Close mini profiler
|
// Close mini profiler
|
||||||
$('.profiler-results .profiler-result').remove();
|
$('.profiler-results .profiler-result').remove();
|
||||||
|
|
||||||
|
@ -9,15 +9,11 @@
|
|||||||
Discourse.UserActivityRoute = Discourse.Route.extend({
|
Discourse.UserActivityRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
model: function() {
|
model: function() {
|
||||||
return this.modelFor('user');
|
return this.modelFor('user').findStream();
|
||||||
},
|
},
|
||||||
|
|
||||||
renderTemplate: function() {
|
renderTemplate: function() {
|
||||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||||
},
|
|
||||||
|
|
||||||
setupController: function(controller, user) {
|
|
||||||
user.filterStream(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -9,16 +9,14 @@
|
|||||||
Discourse.UserPrivateMessagesRoute = Discourse.RestrictedUserRoute.extend({
|
Discourse.UserPrivateMessagesRoute = Discourse.RestrictedUserRoute.extend({
|
||||||
|
|
||||||
model: function() {
|
model: function() {
|
||||||
return this.modelFor('user');
|
return this.modelFor('user').findStream(Discourse.UserAction.GOT_PRIVATE_MESSAGE);
|
||||||
},
|
},
|
||||||
|
|
||||||
renderTemplate: function() {
|
renderTemplate: function() {
|
||||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController: function(controller, user) {
|
setupController: function(controller, stream) {
|
||||||
user.filterStream(Discourse.UserAction.GOT_PRIVATE_MESSAGE);
|
|
||||||
|
|
||||||
var composerController = this.controllerFor('composer');
|
var composerController = this.controllerFor('composer');
|
||||||
Discourse.Draft.get('new_private_message').then(function(data) {
|
Discourse.Draft.get('new_private_message').then(function(data) {
|
||||||
if (data.draft) {
|
if (data.draft) {
|
||||||
@ -32,6 +30,7 @@ Discourse.UserPrivateMessagesRoute = Discourse.RestrictedUserRoute.extend({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,11 +9,29 @@
|
|||||||
Discourse.UserRoute = Discourse.Route.extend({
|
Discourse.UserRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
model: function(params) {
|
model: function(params) {
|
||||||
return Discourse.User.create({username: params.username}).loadDetails();
|
return Discourse.User.create({username: params.username});
|
||||||
},
|
},
|
||||||
|
|
||||||
serialize: function(params) {
|
serialize: function(params) {
|
||||||
return { username: Em.get(params, 'username').toLowerCase() };
|
return { username: Em.get(params, 'username').toLowerCase() };
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController: function(controller, user) {
|
||||||
|
user.findDetails();
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function() {
|
||||||
|
this._super();
|
||||||
|
var user = this.modelFor('user');
|
||||||
|
Discourse.MessageBus.subscribe("/users/" + user.get('username_lower'), function(data) {
|
||||||
|
user.loadUserAction(data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
deactivate: function() {
|
||||||
|
this._super();
|
||||||
|
Discourse.MessageBus.unsubscribe("/users/" + this.modelFor('user').get('username_lower'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,53 +1,54 @@
|
|||||||
<div id='user-info'>
|
{{#with user}}
|
||||||
<nav class='buttons'>
|
<div id='user-info'>
|
||||||
{{#if can_edit}}
|
<nav class='buttons'>
|
||||||
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
{{#if can_edit}}
|
||||||
{{/if}}
|
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
||||||
<br/>
|
{{/if}}
|
||||||
{{#if can_send_private_message_to_user}}
|
<br/>
|
||||||
<button class='btn create' {{action composePrivateMessage}}>
|
{{#if can_send_private_message_to_user}}
|
||||||
<i class='icon icon-envelope-alt'></i>
|
<button class='btn create' {{action composePrivateMessage}}>
|
||||||
{{i18n user.private_message}}
|
<i class='icon icon-envelope-alt'></i>
|
||||||
</button>
|
{{i18n user.private_message}}
|
||||||
{{/if}}
|
</button>
|
||||||
</nav>
|
{{/if}}
|
||||||
<div class='clearfix'></div>
|
</nav>
|
||||||
|
<div class='clearfix'></div>
|
||||||
|
|
||||||
<ul class='action-list nav-stacked side-nav'>
|
<ul class='action-list nav-stacked side-nav'>
|
||||||
{{view Discourse.ActivityFilterView countBinding="statsCountNonPM"}}
|
{{view Discourse.ActivityFilterView countBinding="statsCountNonPM"}}
|
||||||
{{#each statsExcludingPms}}
|
{{#each statsExcludingPms}}
|
||||||
{{view Discourse.ActivityFilterView contentBinding="this"}}
|
{{view Discourse.ActivityFilterView contentBinding="this"}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
<div class='show'>
|
<div class='show'>
|
||||||
<dl>
|
<dl>
|
||||||
{{#if hasWebsite}}
|
{{#if hasWebsite}}
|
||||||
<dt>{{i18n user.website}}:</dt><dd><a {{bindAttr href="website"}} target="_blank">{{websiteName}}</a></dd>
|
<dt>{{i18n user.website}}:</dt><dd><a {{bindAttr href="website"}} target="_blank">{{websiteName}}</a></dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<dt>{{i18n user.created}}:</dt><dd>{{date created_at}}</dd>
|
<dt>{{i18n user.created}}:</dt><dd>{{date created_at}}</dd>
|
||||||
{{#if last_posted_at}}
|
{{#if last_posted_at}}
|
||||||
<dt>{{i18n user.last_posted}}:</dt><dd>{{date last_posted_at}}</dd>
|
<dt>{{i18n user.last_posted}}:</dt><dd>{{date last_posted_at}}</dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if last_seen_at}}
|
{{#if last_seen_at}}
|
||||||
<dt>{{i18n user.last_seen}}:</dt><dd>{{date last_seen_at}}</dd>
|
<dt>{{i18n user.last_seen}}:</dt><dd>{{date last_seen_at}}</dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if invited_by}}
|
{{#if invited_by}}
|
||||||
<dt>{{i18n user.invited_by}}:</dt><dd>{{#linkTo user.activity invited_by}}{{invited_by.username}}{{/linkTo}}</dd>
|
<dt>{{i18n user.invited_by}}:</dt><dd>{{#linkTo user.activity invited_by}}{{invited_by.username}}{{/linkTo}}</dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if email}}
|
{{#if email}}
|
||||||
<dt>{{i18n user.email.title}}:</dt><dd {{bindAttr title="email"}}>{{email}}</dd>
|
<dt>{{i18n user.email.title}}:</dt><dd {{bindAttr title="email"}}>{{email}}</dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<dt>{{i18n user.trust_level}}:</dt><dd>{{trustLevel.name}}</dd>
|
<dt>{{i18n user.trust_level}}:</dt><dd>{{trustLevel.name}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if can_edit}}
|
|
||||||
<div style='margin-top: 10px'>
|
|
||||||
<button class='btn' data-not-implemented='true' disabled title="{{i18n not_implemented}}">{{i18n user.download_archive}}</button>
|
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
|
{{#if can_edit}}
|
||||||
|
<div style='margin-top: 10px'>
|
||||||
|
<button class='btn' data-not-implemented='true' disabled title="{{i18n not_implemented}}">{{i18n user.download_archive}}</button>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{{/with}}
|
||||||
|
|
||||||
{{view Discourse.UserStreamView streamBinding="stream"}}
|
{{view Discourse.UserStreamView streamBinding="model"}}
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
<div id='user-info'>
|
<div id='user-info'>
|
||||||
<nav class='buttons'>
|
{{#with user}}
|
||||||
{{#if can_edit}}
|
<nav class='buttons'>
|
||||||
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
{{#if can_edit}}
|
||||||
{{/if}}
|
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
||||||
<br/>
|
{{/if}}
|
||||||
{{#if can_send_private_message_to_user}}
|
<br/>
|
||||||
<button class='btn create' {{action composePrivateMessage}}>
|
{{#if can_send_private_message_to_user}}
|
||||||
<i class='icon icon-plus'></i>
|
<button class='btn create' {{action composePrivateMessage}}>
|
||||||
{{i18n user.private_message}}
|
<i class='icon icon-plus'></i>
|
||||||
</button>
|
{{i18n user.private_message}}
|
||||||
{{/if}}
|
</button>
|
||||||
</nav>
|
{{/if}}
|
||||||
<div class='clearfix'></div>
|
</nav>
|
||||||
|
<div class='clearfix'></div>
|
||||||
<ul class='action-list nav-stacked side-nav'>
|
|
||||||
{{#each statsPmsOnly}}
|
|
||||||
{{view Discourse.ActivityFilterView contentBinding="this"}}
|
|
||||||
{{/each}}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
<ul class='action-list nav-stacked side-nav'>
|
||||||
|
{{#each statsPmsOnly}}
|
||||||
|
{{view Discourse.ActivityFilterView contentBinding="this"}}
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{/with}}
|
||||||
</div>
|
</div>
|
||||||
{{view Discourse.UserStreamView streamBinding="stream"}}
|
{{view Discourse.UserStreamView streamBinding="model"}}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div id='user-stream'>
|
<div id='user-stream'>
|
||||||
{{#collection contentBinding="stream" itemClass="item"}}
|
{{#each view.stream.content}}
|
||||||
{{#with view.content}}
|
<div class='item'>
|
||||||
<div class='clearfix info'>
|
<div class='clearfix info'>
|
||||||
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||||
<span class='time'>{{date path="created_at" leaveAgo="true"}}</span>
|
<span class='time'>{{date path="created_at" leaveAgo="true"}}</span>
|
||||||
@ -20,7 +20,8 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/with}}
|
</div>
|
||||||
{{/collection}}
|
{{/each}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="user-stream-bottom"></div>
|
<div id="user-stream-bottom"></div>
|
||||||
|
@ -10,6 +10,8 @@ Discourse.ActivityFilterView = Discourse.View.extend({
|
|||||||
tagName: 'li',
|
tagName: 'li',
|
||||||
classNameBindings: ['active'],
|
classNameBindings: ['active'],
|
||||||
|
|
||||||
|
stream: Em.computed.alias('controller.content'),
|
||||||
|
|
||||||
countChanged: function(){
|
countChanged: function(){
|
||||||
this.rerender();
|
this.rerender();
|
||||||
}.observes('count'),
|
}.observes('count'),
|
||||||
@ -17,11 +19,11 @@ Discourse.ActivityFilterView = Discourse.View.extend({
|
|||||||
active: function() {
|
active: function() {
|
||||||
var content = this.get('content');
|
var content = this.get('content');
|
||||||
if (content) {
|
if (content) {
|
||||||
return parseInt(this.get('controller.content.streamFilter'), 10) === parseInt(Em.get(content, 'action_type'), 10);
|
return parseInt(this.get('stream.filter'), 10) === parseInt(Em.get(content, 'action_type'), 10);
|
||||||
} else {
|
} else {
|
||||||
return this.blank('controller.content.streamFilter');
|
return this.blank('stream.filter');
|
||||||
}
|
}
|
||||||
}.property('controller.content.streamFilter', 'content.action_type'),
|
}.property('stream.filter', 'content.action_type'),
|
||||||
|
|
||||||
render: function(buffer) {
|
render: function(buffer) {
|
||||||
var content = this.get('content');
|
var content = this.get('content');
|
||||||
@ -40,7 +42,7 @@ Discourse.ActivityFilterView = Discourse.View.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
click: function() {
|
click: function() {
|
||||||
this.get('controller.content').filterStream(this.get('content.action_type'));
|
this.set('stream.filter', this.get('content.action_type'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
**/
|
**/
|
||||||
Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, {
|
Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, {
|
||||||
templateName: 'user/stream',
|
templateName: 'user/stream',
|
||||||
currentUserBinding: 'Discourse.currentUser',
|
|
||||||
userBinding: 'controller.content',
|
|
||||||
|
|
||||||
scrolled: function(e) {
|
scrolled: function(e) {
|
||||||
|
|
||||||
@ -23,13 +21,16 @@ Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, {
|
|||||||
var docViewTop = $(window).scrollTop();
|
var docViewTop = $(window).scrollTop();
|
||||||
var windowHeight = $(window).height();
|
var windowHeight = $(window).height();
|
||||||
var docViewBottom = docViewTop + windowHeight;
|
var docViewBottom = docViewTop + windowHeight;
|
||||||
this.set('loading', true);
|
|
||||||
if (position.top < docViewBottom) {
|
if (position.top < docViewBottom) {
|
||||||
$userStreamBottom.data('loading', true);
|
$userStreamBottom.data('loading', true);
|
||||||
this.set('loading', true);
|
this.set('loading', true);
|
||||||
|
|
||||||
var userStreamView = this;
|
var userStreamView = this;
|
||||||
this.get('controller.content').loadMoreUserActions().then(function() {
|
var user = this.get('stream.user');
|
||||||
|
var stream = this.get('stream');
|
||||||
|
|
||||||
|
stream.findItems().then(function() {
|
||||||
userStreamView.set('loading', false);
|
userStreamView.set('loading', false);
|
||||||
Em.run.schedule('afterRender', function() {
|
Em.run.schedule('afterRender', function() {
|
||||||
$userStreamBottom.data('loading', null);
|
$userStreamBottom.data('loading', null);
|
||||||
@ -39,15 +40,10 @@ Discourse.UserStreamView = Discourse.View.extend(Discourse.Scrolling, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
willDestroyElement: function() {
|
willDestroyElement: function() {
|
||||||
Discourse.MessageBus.unsubscribe("/users/" + (this.get('user.username').toLowerCase()));
|
|
||||||
this.unbindScrolling();
|
this.unbindScrolling();
|
||||||
},
|
},
|
||||||
|
|
||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
var userSteamView = this;
|
|
||||||
Discourse.MessageBus.subscribe("/users/" + (this.get('user.username').toLowerCase()), function(data) {
|
|
||||||
userSteamView.get('user').loadUserAction(data);
|
|
||||||
});
|
|
||||||
this.bindScrolling();
|
this.bindScrolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +175,19 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_user_from_params
|
||||||
|
username_lower = params[:username].downcase
|
||||||
|
username_lower.gsub!(/\.json$/, '')
|
||||||
|
|
||||||
|
user = User.where(username_lower: username_lower).first
|
||||||
|
raise Discourse::NotFound.new if user.blank?
|
||||||
|
|
||||||
|
guardian.ensure_can_see!(user)
|
||||||
|
user
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_json_error(obj)
|
def render_json_error(obj)
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
class UserActionsController < ApplicationController
|
class UserActionsController < ApplicationController
|
||||||
def index
|
def index
|
||||||
requires_parameters(:user_id)
|
requires_parameters(:username)
|
||||||
per_chunk = 60
|
per_chunk = 60
|
||||||
|
|
||||||
|
user = fetch_user_from_params
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
user_id: params[:user_id].to_i,
|
user_id: user.id,
|
||||||
offset: params[:offset],
|
offset: params[:offset].to_i,
|
||||||
limit: per_chunk,
|
limit: per_chunk,
|
||||||
action_types: (params[:filter] || "").split(",").map(&:to_i),
|
action_types: (params[:filter] || "").split(",").map(&:to_i),
|
||||||
guardian: guardian,
|
guardian: guardian,
|
||||||
@ -29,4 +31,5 @@ class UserActionsController < ApplicationController
|
|||||||
# todo
|
# todo
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@ class UsersController < ApplicationController
|
|||||||
|
|
||||||
before_filter :ensure_logged_in, only: [:username, :update, :change_email, :user_preferences_redirect]
|
before_filter :ensure_logged_in, only: [:username, :update, :change_email, :user_preferences_redirect]
|
||||||
|
|
||||||
# we need to allow account creation with bad CSRF tokens, if people are caching, the CSRF token on the
|
# we need to allow account creation with bad CSRF tokens, if people are caching, the CSRF token on the
|
||||||
# page is going to be empty, this means that server will see an invalid CSRF and blow the session
|
# page is going to be empty, this means that server will see an invalid CSRF and blow the session
|
||||||
# once that happens you can't log in with social
|
# once that happens you can't log in with social
|
||||||
skip_before_filter :verify_authenticity_token, only: [:create]
|
skip_before_filter :verify_authenticity_token, only: [:create]
|
||||||
@ -348,17 +348,6 @@ class UsersController < ApplicationController
|
|||||||
'3019774c067cc2b'
|
'3019774c067cc2b'
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_user_from_params
|
|
||||||
username_lower = params[:username].downcase
|
|
||||||
username_lower.gsub!(/\.json$/, '')
|
|
||||||
|
|
||||||
user = User.where(username_lower: username_lower).first
|
|
||||||
raise Discourse::NotFound.new if user.blank?
|
|
||||||
|
|
||||||
guardian.ensure_can_see!(user)
|
|
||||||
user
|
|
||||||
end
|
|
||||||
|
|
||||||
def honeypot_or_challenge_fails?(params)
|
def honeypot_or_challenge_fails?(params)
|
||||||
params[:password_confirmation] != honeypot_value ||
|
params[:password_confirmation] != honeypot_value ||
|
||||||
params[:challenge] != challenge_value.try(:reverse)
|
params[:challenge] != challenge_value.try(:reverse)
|
||||||
|
@ -62,12 +62,12 @@ class UserSerializer < BasicUserSerializer
|
|||||||
scope.can_send_private_message?(object)
|
scope.can_send_private_message?(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
def stats
|
|
||||||
UserAction.stats(object.id, scope)
|
|
||||||
end
|
|
||||||
|
|
||||||
def can_edit
|
def can_edit
|
||||||
scope.can_edit?(object)
|
scope.can_edit?(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stats
|
||||||
|
UserAction.stats(object.id, scope)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user