mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 18:41:07 +08:00
Each user activity filter has its own URL now.
This commit is contained in:
@ -4,7 +4,7 @@
|
|||||||
<div class='field'>{{i18n user.username.title}}</div>
|
<div class='field'>{{i18n user.username.title}}</div>
|
||||||
<div class='value'>{{username}}</div>
|
<div class='value'>{{username}}</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#linkTo 'user.activity' content class="btn"}}
|
{{#linkTo 'userActivity' class="btn"}}
|
||||||
<i class='icon icon-user'></i>
|
<i class='icon icon-user'></i>
|
||||||
{{i18n admin.user.show_public_profile}}
|
{{i18n admin.user.show_public_profile}}
|
||||||
{{/linkTo}}
|
{{/linkTo}}
|
||||||
|
@ -28,6 +28,26 @@ Discourse.computed = {
|
|||||||
}).property(p1, p2);
|
}).property(p1, p2);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns i18n version of a string based on a property.
|
||||||
|
|
||||||
|
@method i18n
|
||||||
|
@params {String} properties* to format
|
||||||
|
@params {String} format the i18n format string
|
||||||
|
@return {Function} computedProperty function
|
||||||
|
**/
|
||||||
|
i18n: function() {
|
||||||
|
var args = Array.prototype.slice.call(arguments, 0);
|
||||||
|
var format = args.pop();
|
||||||
|
var computed = Ember.computed(function() {
|
||||||
|
var context = this;
|
||||||
|
return I18n.t(format.fmt.apply(format, args.map(function (a) {
|
||||||
|
return context.get(a);
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
return computed.property.apply(computed, args);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Uses an Ember String `fmt` call to format a string. See:
|
Uses an Ember String `fmt` call to format a string. See:
|
||||||
http://emberjs.com/api/classes/Ember.String.html#method_fmt
|
http://emberjs.com/api/classes/Ember.String.html#method_fmt
|
||||||
@ -71,4 +91,5 @@ Discourse.computed = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,37 @@
|
|||||||
|
Discourse.UserActivityRoute = Discourse.Route.extend({
|
||||||
|
renderTemplate: function() {
|
||||||
|
this.render('user_activity', {into: 'user', outlet: 'userOutlet' });
|
||||||
|
},
|
||||||
|
|
||||||
|
model: function() {
|
||||||
|
return this.modelFor('user');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Discourse.UserActivityIndexRoute = Discourse.Route.extend({
|
||||||
|
model: function() {
|
||||||
|
return this.modelFor('user').findStream();
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController: function(controller, model) {
|
||||||
|
this.controllerFor('userActivity').set('stream', model);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(Discourse.UserAction.TYPES).forEach(function (userAction) {
|
||||||
|
Discourse["UserActivity" + userAction.classify() + "Route"] = Discourse.UserActivityIndexRoute.extend({
|
||||||
|
model: function() {
|
||||||
|
return this.modelFor('user').findStream(Discourse.UserAction.TYPES[userAction]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Discourse.UserIndexRoute = Discourse.Route.extend({
|
||||||
|
redirect: function() {
|
||||||
|
this.transitionTo('userActivity.index');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This controller supports all actions on a user's activity stream
|
This controller supports all actions on a user's activity stream
|
||||||
|
|
||||||
@ -6,7 +40,7 @@
|
|||||||
@namespace Discourse
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.UserActivityController = Discourse.ObjectController.extend({
|
Discourse.UserActivityController = Discourse.Controller.extend({
|
||||||
needs: ['composer'],
|
needs: ['composer'],
|
||||||
|
|
||||||
kickOffPrivateMessage: (function() {
|
kickOffPrivateMessage: (function() {
|
||||||
|
@ -1,3 +1,68 @@
|
|||||||
|
/**
|
||||||
|
Base route for showing private messages
|
||||||
|
|
||||||
|
@class UserPrivateMessagesRoute
|
||||||
|
@extends Discourse.Route
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.UserPrivateMessagesRoute = Discourse.Route.extend({
|
||||||
|
renderTemplate: function() {
|
||||||
|
this.render('user_private_messages', {into: 'user', outlet: 'userOutlet' });
|
||||||
|
},
|
||||||
|
|
||||||
|
model: function() {
|
||||||
|
return this.modelFor('user');
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController: function(controller, user) {
|
||||||
|
var composerController = this.controllerFor('composer');
|
||||||
|
controller.set('model', user);
|
||||||
|
Discourse.Draft.get('new_private_message').then(function(data) {
|
||||||
|
if (data.draft) {
|
||||||
|
composerController.open({
|
||||||
|
draft: data.draft,
|
||||||
|
draftKey: 'new_private_message',
|
||||||
|
ignoreIfChanged: true,
|
||||||
|
draftSequence: data.draft_sequence
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
Default private messages route
|
||||||
|
|
||||||
|
@class UserPrivateMessagesIndexRoute
|
||||||
|
@extends Discourse.Route
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.UserPrivateMessagesIndexRoute = Discourse.Route.extend({
|
||||||
|
model: function() {
|
||||||
|
return this.modelFor('user').findStream(Discourse.UserAction.TYPES.messages_received);
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController: function(controller, model) {
|
||||||
|
this.controllerFor('userPrivateMessages').set('stream', model);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
Private messages sent route
|
||||||
|
|
||||||
|
@class UserPrivateMessagesSentRoute
|
||||||
|
@extends Discourse.Route
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.UserPrivateMessagesSentRoute = Discourse.UserPrivateMessagesIndexRoute.extend({
|
||||||
|
model: function() {
|
||||||
|
return this.modelFor('user').findStream(Discourse.UserAction.TYPES.messages_sent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This controller handles actions related to a user's private messages.
|
This controller handles actions related to a user's private messages.
|
||||||
|
|
||||||
|
@ -270,8 +270,12 @@ Discourse.User = Discourse.Model.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
findStream: function(filter) {
|
findStream: function(filter) {
|
||||||
if (Discourse.UserAction.statGroups[filter]) {
|
|
||||||
filter = Discourse.UserAction.statGroups[filter].join(",");
|
// When filtering for replies, include mentions and quotes too
|
||||||
|
if (filter === Discourse.UserAction.TYPES.replies) {
|
||||||
|
filter = [Discourse.UserAction.TYPES.replies,
|
||||||
|
Discourse.UserAction.TYPES.mentions,
|
||||||
|
Discourse.UserAction.TYPES.quotes].join(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
var stream = Discourse.UserStream.create({
|
var stream = Discourse.UserStream.create({
|
||||||
@ -351,7 +355,7 @@ Discourse.User.reopenClass({
|
|||||||
groupStats: function(stats) {
|
groupStats: function(stats) {
|
||||||
var responses = Discourse.UserActionStat.create({
|
var responses = Discourse.UserActionStat.create({
|
||||||
count: 0,
|
count: 0,
|
||||||
action_type: Discourse.UserAction.RESPONSE
|
action_type: Discourse.UserAction.TYPES.replies
|
||||||
});
|
});
|
||||||
|
|
||||||
stats.filterProperty('isResponse').forEach(function (stat) {
|
stats.filterProperty('isResponse').forEach(function (stat) {
|
||||||
@ -363,7 +367,7 @@ Discourse.User.reopenClass({
|
|||||||
|
|
||||||
var insertAt = 1;
|
var insertAt = 1;
|
||||||
result.forEach(function(item, index){
|
result.forEach(function(item, index){
|
||||||
if(item.action_type === Discourse.UserAction.NEW_TOPIC || item.action_type === Discourse.UserAction.POST){
|
if(item.action_type === Discourse.UserAction.TYPES.topics || item.action_type === Discourse.UserAction.TYPES.posts){
|
||||||
insertAt = index + 1;
|
insertAt = index + 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,82 +6,100 @@
|
|||||||
@namespace Discourse
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
var UserActionTypes = {
|
||||||
|
likes_given: 1,
|
||||||
|
likes_received: 2,
|
||||||
|
bookmarks: 3,
|
||||||
|
topics: 4,
|
||||||
|
posts: 5,
|
||||||
|
replies: 6,
|
||||||
|
mentions: 7,
|
||||||
|
quotes: 9,
|
||||||
|
favorites: 10,
|
||||||
|
edits: 11,
|
||||||
|
messages_sent: 12,
|
||||||
|
messages_received: 13
|
||||||
|
};
|
||||||
|
|
||||||
|
var InvertedActionTypes = {};
|
||||||
|
_.each(UserActionTypes, function (k, v) {
|
||||||
|
InvertedActionTypes[k] = v;
|
||||||
|
});
|
||||||
|
|
||||||
Discourse.UserAction = Discourse.Model.extend({
|
Discourse.UserAction = Discourse.Model.extend({
|
||||||
|
|
||||||
descriptionHtml: function() {
|
/**
|
||||||
var action = this.get('action_type');
|
Return an i18n key we will use for the description text of a user action.
|
||||||
var ua = Discourse.UserAction;
|
|
||||||
var actions = [ua.LIKE, ua.WAS_LIKED, ua.STAR, ua.EDIT, ua.BOOKMARK, ua.GOT_PRIVATE_MESSAGE, ua.NEW_PRIVATE_MESSAGE];
|
|
||||||
var icon = "";
|
|
||||||
var sentence = "";
|
|
||||||
var sameUser = (this.get('username') === Discourse.User.current('username'));
|
|
||||||
|
|
||||||
if (action === null || actions.indexOf(action) >= 0) {
|
@property descriptionKey
|
||||||
|
**/
|
||||||
|
descriptionKey: function() {
|
||||||
|
var action = this.get('action_type');
|
||||||
|
if (action === null || Discourse.UserAction.TO_SHOW.indexOf(action) >= 0) {
|
||||||
if (this.get('isPM')) {
|
if (this.get('isPM')) {
|
||||||
icon = '<i class="icon icon-envelope" title="{{i18n user.stream.private_message}}"></i>';
|
return this.get('sameUser') ? 'sent_by_you' : 'sent_by_user';
|
||||||
if (sameUser) {
|
|
||||||
sentence = I18n.t('user_action.sent_by_you', { userUrl: this.get('userUrl') });
|
|
||||||
} else {
|
|
||||||
sentence = I18n.t('user_action.sent_by_user', { user: this.get('name'), userUrl: this.get('userUrl') });
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (sameUser) {
|
return this.get('sameUser') ? 'posted_by_you' : 'posted_by_user';
|
||||||
sentence = I18n.t('user_action.posted_by_you', { userUrl: this.get('userUrl') });
|
|
||||||
} else {
|
|
||||||
sentence = I18n.t('user_action.posted_by_user', { user: this.get('name'), userUrl: this.get('userUrl') });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (action === ua.NEW_TOPIC) {
|
|
||||||
if (sameUser) {
|
|
||||||
sentence = I18n.t('user_action.you_posted_topic', { userUrl: this.get('userUrl'), topicUrl: this.get('replyUrl') });
|
|
||||||
} else {
|
|
||||||
sentence = I18n.t('user_action.user_posted_topic', { user: this.get('name'), userUrl: this.get('userUrl'), topicUrl: this.get('replyUrl') });
|
|
||||||
}
|
|
||||||
} else if (action === ua.POST || action === ua.RESPONSE) {
|
|
||||||
if (this.get('reply_to_post_number')) {
|
|
||||||
if (sameUser) {
|
|
||||||
sentence = I18n.t('user_action.you_replied_to_post', { post_number: '#' + this.get('reply_to_post_number'),
|
|
||||||
userUrl: this.get('userUrl'), postUrl: this.get('postUrl') });
|
|
||||||
} else {
|
|
||||||
sentence = I18n.t('user_action.user_replied_to_post', { user: this.get('name'),
|
|
||||||
post_number: '#' + this.get('reply_to_post_number'), userUrl: this.get('userUrl'), postUrl: this.get('postUrl') });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (sameUser) {
|
|
||||||
sentence = I18n.t('user_action.you_replied_to_topic', { userUrl: this.get('userUrl'),
|
|
||||||
topicUrl: this.get('replyUrl') });
|
|
||||||
} else {
|
|
||||||
sentence = I18n.t('user_action.user_replied_to_topic', { user: this.get('name'),
|
|
||||||
userUrl: this.get('userUrl'), topicUrl: this.get('replyUrl') });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (action === ua.MENTION) {
|
|
||||||
if (sameUser) {
|
|
||||||
sentence = I18n.t('user_action.you_mentioned_user', { user: this.get('target_name'),
|
|
||||||
user1Url: this.get('userUrl'), user2Url: this.get('targetUserUrl') });
|
|
||||||
} else {
|
|
||||||
if (this.get('target_username') === Discourse.User.current('username')) {
|
|
||||||
sentence = I18n.t('user_action.user_mentioned_you', { user: this.get('name'),
|
|
||||||
user1Url: this.get('userUrl'), user2Url: this.get('targetUserUrl') });
|
|
||||||
} else {
|
|
||||||
sentence = I18n.t('user_action.user_mentioned_user', { user: this.get('name'),
|
|
||||||
another_user: this.get('target_name'), user1Url: this.get('userUrl'), user2Url: this.get('targetUserUrl') });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Handlebars.SafeString(icon + " " + sentence);
|
if (this.get('topicType')) {
|
||||||
}.property(),
|
return this.get('sameUser') ? 'you_posted_topic' : 'user_posted_topic';
|
||||||
|
}
|
||||||
|
|
||||||
targetUserUrl: function() {
|
if (this.get('postReplyType')) {
|
||||||
return Discourse.Utilities.userUrl(this.get('target_username'));
|
if (this.get('reply_to_post_number')) {
|
||||||
}.property(),
|
return this.get('sameUser') ? 'you_replied_to_post' : 'user_replied_to_post';
|
||||||
|
} else {
|
||||||
|
return this.get('sameUser') ? 'you_replied_to_topic' : 'user_replied_to_topic';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
userUrl: function() {
|
if (this.get('mentionType')) {
|
||||||
return Discourse.Utilities.userUrl(this.get('username'));
|
if (this.get('sameUser')) {
|
||||||
}.property(),
|
return 'you_mentioned_user';
|
||||||
|
} else {
|
||||||
|
return this.get('targetUser') ? 'user_mentioned_you' : 'user_mentioned_user';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.property('action_type'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the HTML representation of a user action's description, complete with icon.
|
||||||
|
|
||||||
|
@property descriptionHtml
|
||||||
|
**/
|
||||||
|
descriptionHtml: function() {
|
||||||
|
var descriptionKey = this.get('descriptionKey');
|
||||||
|
if (!descriptionKey) { return; }
|
||||||
|
|
||||||
|
var icon = this.get('isPM') ? '<i class="icon icon-envelope" title="{{i18n user.stream.private_message}}"></i>' : '';
|
||||||
|
|
||||||
|
return new Handlebars.SafeString(icon + " " + I18n.t("user_action." + descriptionKey, {
|
||||||
|
userUrl: this.get('userUrl'),
|
||||||
|
replyUrl: this.get('replyUrl'),
|
||||||
|
postUrl: this.get('postUrl'),
|
||||||
|
topicUrl: this.get('replyUrl'),
|
||||||
|
user: this.get('name'),
|
||||||
|
post_number: '#' + this.get('reply_to_post_number'),
|
||||||
|
user1Url: this.get('userUrl'),
|
||||||
|
user2Url: this.get('targetUserUrl'),
|
||||||
|
another_user: this.get('target_name')
|
||||||
|
}));
|
||||||
|
|
||||||
|
}.property('descriptionKey'),
|
||||||
|
|
||||||
|
sameUser: function() {
|
||||||
|
return this.get('username') === Discourse.User.current('username');
|
||||||
|
}.property('username'),
|
||||||
|
|
||||||
|
targetUser: function() {
|
||||||
|
return this.get('target_username') === Discourse.User.current('username');
|
||||||
|
}.property('target_username'),
|
||||||
|
|
||||||
|
targetUserUrl: Discourse.computed.url('target_username', '/users/%@'),
|
||||||
|
userUrl: Discourse.computed.url('username', '/users/%@'),
|
||||||
|
|
||||||
postUrl: function() {
|
postUrl: function() {
|
||||||
return Discourse.Utilities.postUrl(this.get('slug'), this.get('topic_id'), this.get('post_number'));
|
return Discourse.Utilities.postUrl(this.get('slug'), this.get('topic_id'), this.get('post_number'));
|
||||||
@ -91,15 +109,14 @@ Discourse.UserAction = Discourse.Model.extend({
|
|||||||
return Discourse.Utilities.postUrl(this.get('slug'), this.get('topic_id'), this.get('reply_to_post_number'));
|
return Discourse.Utilities.postUrl(this.get('slug'), this.get('topic_id'), this.get('reply_to_post_number'));
|
||||||
}.property(),
|
}.property(),
|
||||||
|
|
||||||
isPM: function() {
|
replyType: Em.computed.equal('action_type', UserActionTypes.replies),
|
||||||
var a = this.get('action_type');
|
postType: Em.computed.equal('action_type', UserActionTypes.posts),
|
||||||
return a === Discourse.UserAction.NEW_PRIVATE_MESSAGE || a === Discourse.UserAction.GOT_PRIVATE_MESSAGE;
|
topicType: Em.computed.equal('action_type', UserActionTypes.topics),
|
||||||
}.property(),
|
messageSentType: Em.computed.equal('action_type', UserActionTypes.messages_sent),
|
||||||
|
messageReceivedType: Em.computed.equal('action_type', UserActionTypes.messages_received),
|
||||||
isPostAction: function() {
|
mentionType: Em.computed.equal('action_type', UserActionTypes.mentions),
|
||||||
var a = this.get('action_type');
|
isPM: Em.computed.or('messageSentType', 'messageReceivedType'),
|
||||||
return a === Discourse.UserAction.RESPONSE || a === Discourse.UserAction.POST || a === Discourse.UserAction.NEW_TOPIC;
|
postReplyType: Em.computed.or('postType', 'replyType'),
|
||||||
}.property(),
|
|
||||||
|
|
||||||
addChild: function(action) {
|
addChild: function(action) {
|
||||||
var groups = this.get("childGroups");
|
var groups = this.get("childGroups");
|
||||||
@ -113,17 +130,16 @@ Discourse.UserAction = Discourse.Model.extend({
|
|||||||
}
|
}
|
||||||
this.set("childGroups", groups);
|
this.set("childGroups", groups);
|
||||||
|
|
||||||
var ua = Discourse.UserAction;
|
|
||||||
var bucket = (function() {
|
var bucket = (function() {
|
||||||
switch (action.action_type) {
|
switch (action.action_type) {
|
||||||
case ua.LIKE:
|
case UserActionTypes.likes_given:
|
||||||
case ua.WAS_LIKED:
|
case UserActionTypes.likes_received:
|
||||||
return "likes";
|
return "likes";
|
||||||
case ua.STAR:
|
case UserActionTypes.favorites:
|
||||||
return "stars";
|
return "stars";
|
||||||
case ua.EDIT:
|
case UserActionTypes.edits:
|
||||||
return "edits";
|
return "edits";
|
||||||
case ua.BOOKMARK:
|
case UserActionTypes.bookmarks:
|
||||||
return "bookmarks";
|
return "bookmarks";
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@ -145,28 +161,29 @@ Discourse.UserAction = Discourse.Model.extend({
|
|||||||
}.property("childGroups"),
|
}.property("childGroups"),
|
||||||
|
|
||||||
switchToActing: function() {
|
switchToActing: function() {
|
||||||
this.set('username', this.get('acting_username'));
|
this.setProperties({
|
||||||
this.set('avatar_template', this.get('acting_avatar_template'));
|
username: this.get('acting_username'),
|
||||||
this.set('name', this.get('acting_name'));
|
avatar_template: this.get('acting_avatar_template'),
|
||||||
|
name: this.get('acting_name')
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Discourse.UserAction.reopenClass({
|
Discourse.UserAction.reopenClass({
|
||||||
collapseStream: function(stream) {
|
collapseStream: function(stream) {
|
||||||
var collapse, collapsed, pos, uniq;
|
var uniq = {},
|
||||||
collapse = [this.LIKE, this.WAS_LIKED, this.STAR, this.EDIT, this.BOOKMARK];
|
collapsed = Em.A(),
|
||||||
uniq = {};
|
pos = 0;
|
||||||
collapsed = Em.A();
|
|
||||||
pos = 0;
|
stream.forEach(function(item) {
|
||||||
_.each(stream, function(item) {
|
var key = "" + item.topic_id + "-" + item.post_number;
|
||||||
var current, found, key;
|
var found = uniq[key];
|
||||||
key = "" + item.topic_id + "-" + item.post_number;
|
|
||||||
found = uniq[key];
|
|
||||||
if (found === void 0) {
|
if (found === void 0) {
|
||||||
if (collapse.indexOf(item.action_type) >= 0) {
|
|
||||||
|
var current;
|
||||||
|
if (Discourse.UserAction.TO_COLLAPSE.indexOf(item.action_type) >= 0) {
|
||||||
current = Discourse.UserAction.create(item);
|
current = Discourse.UserAction.create(item);
|
||||||
current.set('action_type', null);
|
current.setProperties({action_type: null, description: null});
|
||||||
current.set('description', null);
|
|
||||||
item.switchToActing();
|
item.switchToActing();
|
||||||
current.addChild(item);
|
current.addChild(item);
|
||||||
} else {
|
} else {
|
||||||
@ -176,39 +193,37 @@ Discourse.UserAction.reopenClass({
|
|||||||
collapsed[pos] = current;
|
collapsed[pos] = current;
|
||||||
pos += 1;
|
pos += 1;
|
||||||
} else {
|
} else {
|
||||||
if (collapse.indexOf(item.action_type) >= 0) {
|
if (Discourse.UserAction.TO_COLLAPSE.indexOf(item.action_type) >= 0) {
|
||||||
item.switchToActing();
|
item.switchToActing();
|
||||||
return collapsed[found].addChild(item);
|
collapsed[found].addChild(item);
|
||||||
} else {
|
} else {
|
||||||
collapsed[found].set('action_type', item.get('action_type'));
|
collapsed[found].setProperties(item.getProperties('action_type', 'description'));
|
||||||
return collapsed[found].set('description', item.get('description'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return collapsed;
|
return collapsed;
|
||||||
},
|
},
|
||||||
|
|
||||||
// in future we should be sending this through from the server
|
TYPES: UserActionTypes,
|
||||||
LIKE: 1,
|
TYPES_INVERTED: InvertedActionTypes,
|
||||||
WAS_LIKED: 2,
|
|
||||||
BOOKMARK: 3,
|
TO_COLLAPSE: [UserActionTypes.likes_given,
|
||||||
NEW_TOPIC: 4,
|
UserActionTypes.likes_received,
|
||||||
POST: 5,
|
UserActionTypes.favorites,
|
||||||
RESPONSE: 6,
|
UserActionTypes.edits,
|
||||||
MENTION: 7,
|
UserActionTypes.bookmarks],
|
||||||
QUOTE: 9,
|
|
||||||
STAR: 10,
|
TO_SHOW: [
|
||||||
EDIT: 11,
|
UserActionTypes.likes_given,
|
||||||
NEW_PRIVATE_MESSAGE: 12,
|
UserActionTypes.likes_received,
|
||||||
GOT_PRIVATE_MESSAGE: 13
|
UserActionTypes.favorites,
|
||||||
});
|
UserActionTypes.edits,
|
||||||
|
UserActionTypes.bookmarks,
|
||||||
|
UserActionTypes.messages_sent,
|
||||||
|
UserActionTypes.messages_received
|
||||||
|
]
|
||||||
|
|
||||||
Discourse.UserAction.reopenClass({
|
|
||||||
statGroups: (function() {
|
|
||||||
var g = {};
|
|
||||||
g[Discourse.UserAction.RESPONSE] = [Discourse.UserAction.RESPONSE, Discourse.UserAction.MENTION, Discourse.UserAction.QUOTE];
|
|
||||||
return g;
|
|
||||||
})()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,19 +10,17 @@ Discourse.UserActionStat = Discourse.Model.extend({
|
|||||||
|
|
||||||
isPM: function() {
|
isPM: function() {
|
||||||
var actionType = this.get('action_type');
|
var actionType = this.get('action_type');
|
||||||
return actionType === Discourse.UserAction.NEW_PRIVATE_MESSAGE ||
|
return actionType === Discourse.UserAction.TYPES.messages_sent ||
|
||||||
actionType === Discourse.UserAction.GOT_PRIVATE_MESSAGE;
|
actionType === Discourse.UserAction.TYPES.messages_received;
|
||||||
}.property('action_type'),
|
}.property('action_type'),
|
||||||
|
|
||||||
description: function() {
|
description: Discourse.computed.i18n('action_type', 'user_action_groups.%@'),
|
||||||
return I18n.t('user_action_groups.' + this.get('action_type'));
|
|
||||||
}.property('description'),
|
|
||||||
|
|
||||||
isResponse: function() {
|
isResponse: function() {
|
||||||
var actionType = this.get('action_type');
|
var actionType = this.get('action_type');
|
||||||
return actionType === Discourse.UserAction.RESPONSE ||
|
return actionType === Discourse.UserAction.TYPES.replies ||
|
||||||
actionType === Discourse.UserAction.MENTION ||
|
actionType === Discourse.UserAction.TYPES.mentions ||
|
||||||
actionType === Discourse.UserAction.QUOTE;
|
actionType === Discourse.UserAction.TYPES.quotes;
|
||||||
}.property('action_type')
|
}.property('action_type')
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -40,12 +40,24 @@ Discourse.Route.buildRoutes(function() {
|
|||||||
|
|
||||||
// User routes
|
// User routes
|
||||||
this.resource('user', { path: '/users/:username' }, function() {
|
this.resource('user', { path: '/users/:username' }, function() {
|
||||||
this.route('activity', { path: '/' });
|
this.route('index', { path: '/'} );
|
||||||
|
|
||||||
|
this.resource('userActivity', { path: '/activity' }, function() {
|
||||||
|
var resource = this;
|
||||||
|
Object.keys(Discourse.UserAction.TYPES).forEach(function (userAction) {
|
||||||
|
resource.route(userAction, { path: userAction.replace("_", "-") });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.resource('userPrivateMessages', { path: '/private-messages' }, function() {
|
||||||
|
this.route('sent', {path: '/messages-sent'});
|
||||||
|
});
|
||||||
|
|
||||||
this.resource('preferences', { path: '/preferences' }, function() {
|
this.resource('preferences', { path: '/preferences' }, function() {
|
||||||
this.route('username', { path: '/username' });
|
this.route('username', { path: '/username' });
|
||||||
this.route('email', { path: '/email' });
|
this.route('email', { path: '/email' });
|
||||||
});
|
});
|
||||||
this.route('privateMessages', { path: '/private-messages' });
|
|
||||||
this.route('invited', { path: 'invited' });
|
this.route('invited', { path: 'invited' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,7 @@ Discourse.RestrictedUserRoute = Discourse.Route.extend({
|
|||||||
afterModel: function() {
|
afterModel: function() {
|
||||||
var user = this.modelFor('user');
|
var user = this.modelFor('user');
|
||||||
if (!user.get('can_edit')) {
|
if (!user.get('can_edit')) {
|
||||||
this.transitionTo('user.activity', user);
|
this.transitionTo('userActivity');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
This route handles shows a user's activity
|
|
||||||
|
|
||||||
@class UserActivityRoute
|
|
||||||
@extends Discourse.Route
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.UserActivityRoute = Discourse.Route.extend({
|
|
||||||
|
|
||||||
model: function() {
|
|
||||||
return this.modelFor('user').findStream();
|
|
||||||
},
|
|
||||||
|
|
||||||
renderTemplate: function() {
|
|
||||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
/**
|
|
||||||
This route displays a user's private messages.
|
|
||||||
|
|
||||||
@class UserPrivateMessagesRoute
|
|
||||||
@extends Discourse.RestrictedUserRoute
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.UserPrivateMessagesRoute = Discourse.RestrictedUserRoute.extend({
|
|
||||||
|
|
||||||
model: function() {
|
|
||||||
return this.modelFor('user').findStream(Discourse.UserAction.GOT_PRIVATE_MESSAGE);
|
|
||||||
},
|
|
||||||
|
|
||||||
renderTemplate: function() {
|
|
||||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
|
||||||
},
|
|
||||||
|
|
||||||
setupController: function(controller, stream) {
|
|
||||||
var composerController = this.controllerFor('composer');
|
|
||||||
controller.set('model', stream);
|
|
||||||
Discourse.Draft.get('new_private_message').then(function(data) {
|
|
||||||
if (data.draft) {
|
|
||||||
composerController.open({
|
|
||||||
draft: data.draft,
|
|
||||||
draftKey: 'new_private_message',
|
|
||||||
ignoreIfChanged: true,
|
|
||||||
draftSequence: data.draft_sequence
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class='current-user'>
|
<li class='current-user'>
|
||||||
{{#if currentUser}}
|
{{#if currentUser}}
|
||||||
{{#titledLinkTo 'user.activity' currentUser titleKey="current_user" class="icon"}}{{avatar currentUser imageSize="medium" }}{{/titledLinkTo}}
|
{{#titledLinkTo 'user' currentUser titleKey="current_user" class="icon"}}{{avatar currentUser imageSize="medium" }}{{/titledLinkTo}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="icon not-logged-in-avatar" {{action showLogin}}><i class='icon-user'></i></div>
|
<div class="icon not-logged-in-avatar" {{action showLogin}}><i class='icon-user'></i></div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{{#with user}}
|
{{#with model}}
|
||||||
<div id='user-info'>
|
<div id='user-info'>
|
||||||
<nav class='buttons'>
|
<nav class='buttons'>
|
||||||
{{#if can_edit}}
|
{{#if can_edit}}
|
||||||
@ -15,9 +15,9 @@
|
|||||||
<div class='clearfix'></div>
|
<div class='clearfix'></div>
|
||||||
|
|
||||||
<ul class='action-list nav-stacked side-nav'>
|
<ul class='action-list nav-stacked side-nav'>
|
||||||
{{activityFilter count=statsCountNonPM}}
|
{{activityFilter count=statsCountNonPM user=this}}
|
||||||
{{#each statsExcludingPms}}
|
{{#each stat in statsExcludingPms}}
|
||||||
{{activityFilter content=this}}
|
{{activityFilter content=stat user=model}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
<div class='show'>
|
<div class='show'>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
<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 'userActivity' 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>
|
||||||
@ -53,4 +53,4 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
|
|
||||||
{{userStream stream=model}}
|
{{userStream stream=stream}}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div id='user-info'>
|
<div id='user-info'>
|
||||||
{{#with user}}
|
{{#with model}}
|
||||||
<nav class='buttons'>
|
<nav class='buttons'>
|
||||||
{{#if can_edit}}
|
{{#if can_edit}}
|
||||||
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
||||||
@ -15,11 +15,12 @@
|
|||||||
<div class='clearfix'></div>
|
<div class='clearfix'></div>
|
||||||
|
|
||||||
<ul class='action-list nav-stacked side-nav'>
|
<ul class='action-list nav-stacked side-nav'>
|
||||||
{{#each statsPmsOnly}}
|
{{#each stat in statsPmsOnly}}
|
||||||
{{activityFilter content=this}}
|
{{activityFilter content=stat user=model}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
</div>
|
</div>
|
||||||
{{userStream stream=model}}
|
|
||||||
|
{{userStream stream=stream}}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div id='user-stream'>
|
<div id='user-stream'>
|
||||||
{{#each view.stream.content}}
|
{{#each view.stream.content}}
|
||||||
<div {{bindAttr class=":item hidden:hidden deleted:deleted"}}>
|
<div {{bindAttr class=":item hidden deleted"}}>
|
||||||
<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>
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li>
|
<li>
|
||||||
{{#linkTo 'user.activity'}}{{i18n user.activity_stream}}{{/linkTo}}
|
{{#linkTo 'userActivity'}}{{i18n user.activity_stream}}{{/linkTo}}
|
||||||
</li>
|
</li>
|
||||||
{{#if canSeePrivateMessages}}
|
{{#if canSeePrivateMessages}}
|
||||||
<li>
|
<li>
|
||||||
{{#linkTo "user.privateMessages"}}{{i18n user.private_messages}}{{/linkTo}}
|
{{#linkTo 'userPrivateMessages'}}{{i18n user.private_messages}}{{/linkTo}}
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<li>
|
<li>
|
||||||
|
@ -30,7 +30,6 @@ Discourse.ActionsHistoryView = Discourse.View.extend({
|
|||||||
if (c.get('usersExpanded')) {
|
if (c.get('usersExpanded')) {
|
||||||
var postUrl;
|
var postUrl;
|
||||||
c.get('users').forEach(function(u) {
|
c.get('users').forEach(function(u) {
|
||||||
console.log(u);
|
|
||||||
iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + (u.get('username_lower')) + "\">";
|
iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + (u.get('username_lower')) + "\">";
|
||||||
if (u.post_url) {
|
if (u.post_url) {
|
||||||
postUrl = postUrl || u.post_url;
|
postUrl = postUrl || u.post_url;
|
||||||
|
@ -10,9 +10,8 @@ Discourse.ActivityFilterView = Discourse.View.extend({
|
|||||||
tagName: 'li',
|
tagName: 'li',
|
||||||
classNameBindings: ['active', 'noGlyph'],
|
classNameBindings: ['active', 'noGlyph'],
|
||||||
|
|
||||||
stream: Em.computed.alias('controller.content'),
|
stream: Em.computed.alias('controller.stream'),
|
||||||
shouldRerender: Discourse.View.renderIfChanged('count'),
|
shouldRerender: Discourse.View.renderIfChanged('count'),
|
||||||
|
|
||||||
noGlyph: Em.computed.empty('icon'),
|
noGlyph: Em.computed.empty('icon'),
|
||||||
|
|
||||||
active: function() {
|
active: function() {
|
||||||
@ -24,62 +23,57 @@ Discourse.ActivityFilterView = Discourse.View.extend({
|
|||||||
}
|
}
|
||||||
}.property('stream.filter', 'content.action_type'),
|
}.property('stream.filter', 'content.action_type'),
|
||||||
|
|
||||||
|
activityCount: function() {
|
||||||
|
return this.get('content.count') || this.get('count');
|
||||||
|
}.property('content.count', 'count'),
|
||||||
|
|
||||||
|
typeKey: function() {
|
||||||
|
|
||||||
|
var actionType = this.get('content.action_type');
|
||||||
|
if (actionType === Discourse.UserAction.TYPES.messages_received) { return ""; }
|
||||||
|
|
||||||
|
var result = Discourse.UserAction.TYPES_INVERTED[actionType];
|
||||||
|
if (!result) { return ""; }
|
||||||
|
|
||||||
|
// We like our URLS to have hyphens, not underscores
|
||||||
|
return "/" + result.replace("_", "-");
|
||||||
|
}.property('content.action_type'),
|
||||||
|
|
||||||
|
url: function() {
|
||||||
|
var section = this.get('content.isPM') ? "/private-messages" : "/activity";
|
||||||
|
return "/users/" + this.get('user.username_lower') + section + this.get('typeKey');
|
||||||
|
}.property('typeKey'),
|
||||||
|
|
||||||
|
description: function() {
|
||||||
|
return this.get('content.description') || I18n.t("user.filters.all");
|
||||||
|
}.property('content.description'),
|
||||||
|
|
||||||
render: function(buffer) {
|
render: function(buffer) {
|
||||||
var content = this.get("content");
|
buffer.push("<a href='" + this.get('url') + "'>");
|
||||||
var count, description;
|
|
||||||
|
|
||||||
if (content) {
|
|
||||||
count = Em.get(content, "count");
|
|
||||||
description = Em.get(content, "description");
|
|
||||||
} else {
|
|
||||||
count = this.get("count");
|
|
||||||
description = I18n.t("user.filters.all");
|
|
||||||
}
|
|
||||||
|
|
||||||
var icon = this.get('icon');
|
var icon = this.get('icon');
|
||||||
|
if (icon) {
|
||||||
buffer.push("<a href='#'>");
|
|
||||||
if(icon) {
|
|
||||||
buffer.push("<i class='glyph icon icon-" + icon + "'></i> ");
|
buffer.push("<i class='glyph icon icon-" + icon + "'></i> ");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.push(description +
|
buffer.push(this.get('description') + " <span class='count'>(" + this.get('activityCount') + ")</span>");
|
||||||
" <span class='count'>(" + count + ")</span>");
|
|
||||||
|
|
||||||
|
|
||||||
buffer.push("<span class='icon-chevron-right'></span></a>");
|
buffer.push("<span class='icon-chevron-right'></span></a>");
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
icon: function(){
|
icon: function(){
|
||||||
var action_type = parseInt(this.get("content.action_type"),10);
|
switch(parseInt(this.get('content.action_type'),10)) {
|
||||||
var icon;
|
case Discourse.UserAction.TYPES.likes_received:
|
||||||
|
return "heart";
|
||||||
switch(action_type){
|
case Discourse.UserAction.TYPES.bookmarks:
|
||||||
case Discourse.UserAction.WAS_LIKED:
|
return "bookmark";
|
||||||
icon = "heart";
|
case Discourse.UserAction.TYPES.edits:
|
||||||
break;
|
return "pencil";
|
||||||
case Discourse.UserAction.BOOKMARK:
|
case Discourse.UserAction.TYPES.replies:
|
||||||
icon = "bookmark";
|
return "reply";
|
||||||
break;
|
case Discourse.UserAction.TYPES.favorites:
|
||||||
case Discourse.UserAction.EDIT:
|
return "star";
|
||||||
icon = "pencil";
|
|
||||||
break;
|
|
||||||
case Discourse.UserAction.RESPONSE:
|
|
||||||
icon = "reply";
|
|
||||||
break;
|
|
||||||
case Discourse.UserAction.STAR:
|
|
||||||
icon = "star";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}.property("content.action_type")
|
||||||
|
|
||||||
return icon;
|
|
||||||
}.property("content.action_type"),
|
|
||||||
|
|
||||||
click: function() {
|
|
||||||
this.set('stream.filter', this.get('content.action_type'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Discourse.View.registerHelper('activityFilter', Discourse.ActivityFilterView);
|
Discourse.View.registerHelper('activityFilter', Discourse.ActivityFilterView);
|
||||||
|
@ -18,12 +18,12 @@ Discourse.UserPrivateMessagesView = Discourse.View.extend({
|
|||||||
|
|
||||||
inbox: function(evt) {
|
inbox: function(evt) {
|
||||||
this.selectCurrent(evt);
|
this.selectCurrent(evt);
|
||||||
return this.set('controller.filter', Discourse.UserAction.GOT_PRIVATE_MESSAGE);
|
return this.set('controller.filter', Discourse.UserAction.TYPES.messages_received);
|
||||||
},
|
},
|
||||||
|
|
||||||
sentMessages: function(evt) {
|
sentMessages: function(evt) {
|
||||||
this.selectCurrent(evt);
|
this.selectCurrent(evt);
|
||||||
return this.set('controller.filter', Discourse.UserAction.NEW_PRIVATE_MESSAGE);
|
return this.set('controller.filter', Discourse.UserAction.TYPES.messages_sent);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -11,15 +11,17 @@
|
|||||||
|
|
||||||
// Stuff we need to load first
|
// Stuff we need to load first
|
||||||
//= require_tree ./discourse/mixins
|
//= require_tree ./discourse/mixins
|
||||||
|
//= require ./discourse/components/computed
|
||||||
//= require ./discourse/views/view
|
//= require ./discourse/views/view
|
||||||
//= require ./discourse/components/debounce
|
//= require ./discourse/components/debounce
|
||||||
|
//= require ./discourse/models/model
|
||||||
|
//= require ./discourse/models/user_action
|
||||||
//= require ./discourse/controllers/controller
|
//= require ./discourse/controllers/controller
|
||||||
//= require ./discourse/controllers/object_controller
|
//= require ./discourse/controllers/object_controller
|
||||||
//= require ./discourse/views/modal/modal_body_view
|
//= require ./discourse/views/modal/modal_body_view
|
||||||
//= require ./discourse/views/combobox_view
|
//= require ./discourse/views/combobox_view
|
||||||
//= require ./discourse/views/buttons/button_view
|
//= require ./discourse/views/buttons/button_view
|
||||||
//= require ./discourse/views/buttons/dropdown_button_view
|
//= require ./discourse/views/buttons/dropdown_button_view
|
||||||
//= require ./discourse/models/model
|
|
||||||
//= require ./discourse/routes/discourse_route
|
//= require ./discourse/routes/discourse_route
|
||||||
//= require ./discourse/routes/discourse_restricted_user_route
|
//= require ./discourse/routes/discourse_restricted_user_route
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ Discourse::Application.routes.draw do
|
|||||||
|
|
||||||
get 'user_preferences' => 'users#user_preferences_redirect'
|
get 'user_preferences' => 'users#user_preferences_redirect'
|
||||||
get 'users/:username/private-messages' => 'user_actions#private_messages', constraints: {username: USERNAME_ROUTE_FORMAT}
|
get 'users/:username/private-messages' => 'user_actions#private_messages', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
|
get 'users/:username/private-messages/:filter' => 'user_actions#private_messages', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
get 'users/:username' => 'users#show', constraints: {username: USERNAME_ROUTE_FORMAT}
|
get 'users/:username' => 'users#show', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
put 'users/:username' => 'users#update', constraints: {username: USERNAME_ROUTE_FORMAT}
|
put 'users/:username' => 'users#update', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
get 'users/:username/preferences' => 'users#preferences', constraints: {username: USERNAME_ROUTE_FORMAT}, as: :email_preferences
|
get 'users/:username/preferences' => 'users#preferences', constraints: {username: USERNAME_ROUTE_FORMAT}, as: :email_preferences
|
||||||
@ -129,6 +130,8 @@ Discourse::Application.routes.draw do
|
|||||||
get 'users/:username/avatar(/:size)' => 'users#avatar', constraints: {username: USERNAME_ROUTE_FORMAT}
|
get 'users/:username/avatar(/:size)' => 'users#avatar', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
get 'users/:username/invited' => 'users#invited', constraints: {username: USERNAME_ROUTE_FORMAT}
|
get 'users/:username/invited' => 'users#invited', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
post 'users/:username/send_activation_email' => 'users#send_activation_email', constraints: {username: USERNAME_ROUTE_FORMAT}
|
post 'users/:username/send_activation_email' => 'users#send_activation_email', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
|
get 'users/:username/activity' => 'users#show', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
|
get 'users/:username/activity/:filter' => 'users#show', constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||||
|
|
||||||
resources :uploads
|
resources :uploads
|
||||||
|
|
||||||
|
@ -6,7 +6,14 @@ task 'integration:create_fixtures' => :environment do
|
|||||||
fixtures = {
|
fixtures = {
|
||||||
list: ["/latest.json", "/categories.json", "/category/bug.json"],
|
list: ["/latest.json", "/categories.json", "/category/bug.json"],
|
||||||
topic: ["/t/280.json"],
|
topic: ["/t/280.json"],
|
||||||
user: ["/users/eviltrout.json", "/user_actions.json?offset=0&username=eviltrout"],
|
user: ["/users/eviltrout.json",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout&filter=4",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout&filter=5",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout&filter=6,7,9",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout&filter=1",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout&filter=2",
|
||||||
|
"/user_actions.json?offset=0&username=eviltrout&filter=11"],
|
||||||
static: ["/faq", '/tos', '/privacy']
|
static: ["/faq", '/tos', '/privacy']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ test("fmt", function() {
|
|||||||
test("url without a prefix", function() {
|
test("url without a prefix", function() {
|
||||||
var t = testClass.create({ username: 'eviltrout' });
|
var t = testClass.create({ username: 'eviltrout' });
|
||||||
equal(t.get('userUrl'), "/users/eviltrout");
|
equal(t.get('userUrl'), "/users/eviltrout");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("url with a prefix", function() {
|
test("url with a prefix", function() {
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,12 +1,21 @@
|
|||||||
integration("User");
|
integration("User");
|
||||||
|
|
||||||
test("Profile", function() {
|
test("Activity Streams", function() {
|
||||||
|
expect(14);
|
||||||
|
|
||||||
visit("/users/eviltrout").then(function() {
|
var streamTest = function(url) {
|
||||||
expect(2);
|
visit(url).then(function() {
|
||||||
|
ok(exists(".user-heading"), "The heading is rendered");
|
||||||
|
ok(exists("#user-stream"), "The stream is rendered");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
ok(exists(".user-heading"), "The heading is rendered");
|
streamTest("/users/eviltrout");
|
||||||
ok(exists("#user-stream"), "The stream is rendered");
|
streamTest("/users/eviltrout/activity/topics");
|
||||||
});
|
streamTest("/users/eviltrout/activity/posts");
|
||||||
|
streamTest("/users/eviltrout/activity/replies");
|
||||||
|
streamTest("/users/eviltrout/activity/likes-given");
|
||||||
|
streamTest("/users/eviltrout/activity/likes-received");
|
||||||
|
streamTest("/users/eviltrout/activity/edits");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -3,17 +3,17 @@ module("Discourse.UserAction");
|
|||||||
test("collapsing likes", function () {
|
test("collapsing likes", function () {
|
||||||
var actions = Discourse.UserAction.collapseStream([
|
var actions = Discourse.UserAction.collapseStream([
|
||||||
Discourse.UserAction.create({
|
Discourse.UserAction.create({
|
||||||
action_type: Discourse.UserAction.LIKE,
|
action_type: Discourse.UserAction.TYPES.likes_given,
|
||||||
topic_id: 1,
|
topic_id: 1,
|
||||||
user_id: 1,
|
user_id: 1,
|
||||||
post_number: 1
|
post_number: 1
|
||||||
}), Discourse.UserAction.create({
|
}), Discourse.UserAction.create({
|
||||||
action_type: Discourse.UserAction.EDIT,
|
action_type: Discourse.UserAction.TYPES.edits,
|
||||||
topic_id: 2,
|
topic_id: 2,
|
||||||
user_id: 1,
|
user_id: 1,
|
||||||
post_number: 1
|
post_number: 1
|
||||||
}), Discourse.UserAction.create({
|
}), Discourse.UserAction.create({
|
||||||
action_type: Discourse.UserAction.LIKE,
|
action_type: Discourse.UserAction.TYPES.likes_given,
|
||||||
topic_id: 1,
|
topic_id: 1,
|
||||||
user_id: 2,
|
user_id: 2,
|
||||||
post_number: 1
|
post_number: 1
|
||||||
|
Reference in New Issue
Block a user