mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Show topics as a list of topics on the User Stream.
This commit is contained in:
@@ -13,5 +13,3 @@
|
||||
|
||||
{{collection contentBinding="filteredContent" classNames="form-horizontal settings" itemViewClass="Discourse.SiteSettingView"}}
|
||||
|
||||
<!-- will remove as soon as I figure out what is going on -->
|
||||
<p><small>Diagnostics: last_message_processed {{diags.last_message_processed}}</small></p>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
{{#with view.content}}
|
||||
<div class='span4 offset1'>
|
||||
<h3>{{unbound setting}}</h3>
|
||||
</div>
|
||||
<div class="span11">
|
||||
<label>
|
||||
{{view Ember.Checkbox checkedBinding="enabled" value="true"}}
|
||||
{{unbound description}}
|
||||
</label>
|
||||
</div>
|
||||
{{/with}}
|
||||
<div class='span4 offset1'>
|
||||
<h3>{{unbound setting}}</h3>
|
||||
</div>
|
||||
<div class="span11">
|
||||
<label>
|
||||
{{view Ember.Checkbox checkedBinding="enabled" value="true"}}
|
||||
{{unbound description}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
{{#with view.content}}
|
||||
<div class='span4 offset1'>
|
||||
<h3>{{unbound setting}}</h3>
|
||||
<div class='span4 offset1'>
|
||||
<h3>{{unbound setting}}</h3>
|
||||
</div>
|
||||
<div class="span11">
|
||||
{{combobox valueAttribute="value" content=validValues value=value none=allowsNone}}
|
||||
<div class='desc'>{{unbound description}}</div>
|
||||
</div>
|
||||
{{#if dirty}}
|
||||
<div class='span3'>
|
||||
<button class='btn ok' {{action save this}}><i class='icon-ok'></i></button>
|
||||
<button class='btn cancel' {{action cancel this}}><i class='icon-remove'></i></button>
|
||||
</div>
|
||||
<div class="span11">
|
||||
{{combobox valueAttribute="value" content=validValues value=value none=allowsNone}}
|
||||
<div class='desc'>{{unbound description}}</div>
|
||||
</div>
|
||||
{{#if dirty}}
|
||||
<div class='span3'>
|
||||
<button class='btn ok' {{action save this}}><i class='icon-ok'></i></button>
|
||||
<button class='btn cancel' {{action cancel this}}><i class='icon-remove'></i></button>
|
||||
</div>
|
||||
{{else}}
|
||||
{{#if overridden}}
|
||||
<button class='btn' href='#' {{action resetDefault this}}>{{i18n admin.site_settings.reset}}</button>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if overridden}}
|
||||
<button class='btn' href='#' {{action resetDefault this}}>{{i18n admin.site_settings.reset}}</button>
|
||||
{{/if}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
{{#with view.content}}
|
||||
<div class='span4 offset1'>
|
||||
<h3>{{unbound setting}}</h3>
|
||||
<div class='span4 offset1'>
|
||||
<h3>{{unbound setting}}</h3>
|
||||
</div>
|
||||
<div class="span11">
|
||||
{{textField value=value classNames="input-xxlarge"}}
|
||||
<div class='desc'>{{unbound description}}</div>
|
||||
</div>
|
||||
{{#if dirty}}
|
||||
<div class='span3'>
|
||||
<button class='btn ok' {{action save this}}><i class='icon-ok'></i></button>
|
||||
<button class='btn cancel' {{action cancel this}}><i class='icon-remove'></i></button>
|
||||
</div>
|
||||
<div class="span11">
|
||||
{{textField value=value classNames="input-xxlarge"}}
|
||||
<div class='desc'>{{unbound description}}</div>
|
||||
</div>
|
||||
{{#if dirty}}
|
||||
<div class='span3'>
|
||||
<button class='btn ok' {{action save this}}><i class='icon-ok'></i></button>
|
||||
<button class='btn cancel' {{action cancel this}}><i class='icon-remove'></i></button>
|
||||
</div>
|
||||
{{else}}
|
||||
{{#if overridden}}
|
||||
<button class='btn' href='#' {{action resetDefault this}}>{{i18n admin.site_settings.reset}}</button>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if overridden}}
|
||||
<button class='btn' href='#' {{action resetDefault this}}>{{i18n admin.site_settings.reset}}</button>
|
||||
{{/if}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
|
||||
@@ -64,6 +64,9 @@ Discourse.URL = Em.Object.createWithMixins({
|
||||
if (this.navigatedToListMore(oldPath, path)) { return; }
|
||||
if (this.navigatedToHome(oldPath, path)) { return; }
|
||||
|
||||
if (path.match(/^\/?users\/[^\/]+$/)) {
|
||||
path += "/activity";
|
||||
}
|
||||
// Be wary of looking up the router. In this case, we have links in our
|
||||
// HTML, say form compiled markdown posts, that need to be routed.
|
||||
var router = this.get('router');
|
||||
|
||||
@@ -87,7 +87,7 @@ Discourse.Utilities = {
|
||||
},
|
||||
|
||||
userUrl: function(username) {
|
||||
return Discourse.getURL("/users/" + username);
|
||||
return Discourse.getURL("/users/" + username.toLowerCase());
|
||||
},
|
||||
|
||||
emailValid: function(email) {
|
||||
|
||||
@@ -24,6 +24,16 @@ Discourse.ListController = Discourse.Controller.extend({
|
||||
});
|
||||
}.property(),
|
||||
|
||||
createTopicText: function() {
|
||||
if (this.get('category.name')) {
|
||||
return I18n.t("topic.create_in", {
|
||||
categoryName: this.get('category.name')
|
||||
});
|
||||
} else {
|
||||
return I18n.t("topic.create");
|
||||
}
|
||||
}.property('category.name'),
|
||||
|
||||
/**
|
||||
Refresh our current topic list
|
||||
|
||||
|
||||
@@ -81,11 +81,11 @@ Discourse.ListTopicsController = Discourse.ObjectController.extend({
|
||||
}.property('allLoaded', 'topics.length'),
|
||||
|
||||
loadMore: function() {
|
||||
this.set('loadingMore', true);
|
||||
var listTopicsController = this;
|
||||
return this.get('model').loadMoreTopics().then(function(hasMoreTopics) {
|
||||
listTopicsController.set('loadingMore', false);
|
||||
return hasMoreTopics;
|
||||
var topicList = this.get('model');
|
||||
return topicList.loadMoreTopics().then(function(moreUrl) {
|
||||
if (!Em.isEmpty(moreUrl)) {
|
||||
Discourse.URL.replaceState(Discourse.getURL("/") + topicList.get('filter') + "/more");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +1,3 @@
|
||||
/**
|
||||
The route for editing a user's "About Me" bio.
|
||||
|
||||
@class PreferencesAboutRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesAboutRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.setProperties({ model: model, newBio: model.get('bio_raw') });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
events: {
|
||||
changeAbout: function() {
|
||||
var route = this;
|
||||
var controller = route.controllerFor('preferencesAbout');
|
||||
|
||||
controller.setProperties({ saving: true });
|
||||
return controller.get('model').save().then(function() {
|
||||
controller.set('saving', false);
|
||||
route.transitionTo('user.index');
|
||||
}, function() {
|
||||
// model failed to save
|
||||
controller.set('saving', false);
|
||||
alert(I18n.t('generic_error'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating your "About Me" bio
|
||||
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
/**
|
||||
The common route stuff for a user's preference
|
||||
|
||||
@class PreferencesRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating one's preferences
|
||||
|
||||
|
||||
@@ -1,32 +1,3 @@
|
||||
/**
|
||||
The route for editing a user's email
|
||||
|
||||
@class PreferencesEmailRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesEmailRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.setProperties({ model: model, newEmail: model.get('email') });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating one's email address
|
||||
|
||||
|
||||
@@ -1,32 +1,3 @@
|
||||
/**
|
||||
The route for updating a user's username
|
||||
|
||||
@class PreferencesUsernameRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesUsernameRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
controller.setProperties({ model: user, newUsername: user.get('username') });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating one's username
|
||||
|
||||
|
||||
@@ -1,82 +1,3 @@
|
||||
/**
|
||||
The base route for showing an activity stream.
|
||||
|
||||
@class UserActivityRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserActivityRoute = Discourse.Route.extend({
|
||||
renderTemplate: function() {
|
||||
this.render('user_activity', {into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
this.controllerFor('userActivity').set('model', user);
|
||||
|
||||
var composerController = this.controllerFor('composer');
|
||||
controller.set('model', user);
|
||||
if (Discourse.User.current()) {
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.UserActivityIndexRoute = Discourse.Route.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user').findStream(this.get('userActionType'));
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('user_stream', {into: 'user_activity', outlet: 'activity'});
|
||||
},
|
||||
|
||||
setupController: function() {
|
||||
this.controllerFor('user_activity').set('userActionType', this.get('userActionType'));
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.UserIndexRoute = Discourse.UserActivityRoute.extend({
|
||||
renderTemplate: function() {
|
||||
this._super();
|
||||
this.render('user_stream', {into: 'user_activity', outlet: 'activity'});
|
||||
},
|
||||
|
||||
model: function() {
|
||||
return this.modelFor('user').findStream();
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
this.controllerFor('userActivity').set('model', this.modelFor('user'));
|
||||
this.set('model', model);
|
||||
}
|
||||
});
|
||||
|
||||
// Build all the filter routes
|
||||
Object.keys(Discourse.UserAction.TYPES).forEach(function (userAction) {
|
||||
Discourse["UserActivity" + userAction.classify() + "Route"] = Discourse.UserActivityIndexRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES[userAction]
|
||||
});
|
||||
});
|
||||
|
||||
// // Build the private message routes
|
||||
Discourse.UserPrivateMessagesRoute = Discourse.UserActivityRoute.extend({});
|
||||
Discourse.UserPrivateMessagesIndexRoute = Discourse.UserActivityMessagesReceivedRoute;
|
||||
Discourse.UserPrivateMessagesSentRoute = Discourse.UserActivityMessagesSentRoute;
|
||||
|
||||
/**
|
||||
This controller supports all actions on a user's activity stream
|
||||
|
||||
|
||||
39
app/assets/javascripts/discourse/mixins/load_more.js
Normal file
39
app/assets/javascripts/discourse/mixins/load_more.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
This mixin provides the ability to load more items for a view which is
|
||||
scrolled to the bottom.
|
||||
|
||||
@class Discourse.LoadMore
|
||||
@extends Ember.Mixin
|
||||
@uses Discourse.Scrolling
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.LoadMore = Em.Mixin.create(Discourse.Scrolling, {
|
||||
|
||||
scrolled: function(e) {
|
||||
var eyeline = this.get('eyeline');
|
||||
if (eyeline) { eyeline.update(); }
|
||||
},
|
||||
|
||||
loadMore: function() {
|
||||
console.error('loadMore() not defined');
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
var eyeline = new Discourse.Eyeline(this.get('eyelineSelector'));
|
||||
this.set('eyeline', eyeline);
|
||||
|
||||
var paginatedTopicListView = this;
|
||||
eyeline.on('sawBottom', function() {
|
||||
paginatedTopicListView.loadMore();
|
||||
});
|
||||
this.bindScrolling();
|
||||
},
|
||||
|
||||
willRemoveElement: function() {
|
||||
this._super();
|
||||
this.unbindScrolling();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -23,32 +23,37 @@ Discourse.TopicList = Discourse.Model.extend({
|
||||
},
|
||||
|
||||
loadMoreTopics: function() {
|
||||
var moreUrl, _this = this;
|
||||
|
||||
if (moreUrl = this.get('more_topics_url')) {
|
||||
Discourse.URL.replaceState(Discourse.getURL("/") + (this.get('filter')) + "/more");
|
||||
if (this.get('loadingMore')) { return Ember.RSVP.reject(); }
|
||||
|
||||
var moreUrl = this.get('more_topics_url');
|
||||
if (moreUrl) {
|
||||
|
||||
var topicList = this;
|
||||
this.set('loadingMore', true);
|
||||
|
||||
return Discourse.ajax({url: moreUrl}).then(function (result) {
|
||||
var newTopics, topics, topicsAdded = 0;
|
||||
var topicsAdded = 0;
|
||||
if (result) {
|
||||
// the new topics loaded from the server
|
||||
newTopics = Discourse.TopicList.topicsFrom(result);
|
||||
topics = _this.get("topics");
|
||||
var newTopics = Discourse.TopicList.topicsFrom(result);
|
||||
var topics = topicList.get("topics");
|
||||
|
||||
_this.forEachNew(newTopics, function(t) {
|
||||
topicList.forEachNew(newTopics, function(t) {
|
||||
t.set('highlight', topicsAdded++ === 0);
|
||||
topics.pushObject(t);
|
||||
});
|
||||
|
||||
_this.set('more_topics_url', result.topic_list.more_topics_url);
|
||||
Discourse.set('transient.topicsList', _this);
|
||||
topicList.set('more_topics_url', result.topic_list.more_topics_url);
|
||||
Discourse.set('transient.topicsList', topicList);
|
||||
topicList.set('loadingMore', false);
|
||||
|
||||
return result.topic_list.more_topics_url;
|
||||
}
|
||||
return result.topic_list.more_topics_url;
|
||||
});
|
||||
} else {
|
||||
// Return a promise indicating no more results
|
||||
return Ember.Deferred.promise(function (p) {
|
||||
p.resolve(false);
|
||||
});
|
||||
return Ember.RSVP.reject();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -109,6 +114,9 @@ Discourse.TopicList.reopenClass({
|
||||
categories = this.extractByKey(result.categories, Discourse.Category);
|
||||
users = this.extractByKey(result.users, Discourse.User);
|
||||
topics = Em.A();
|
||||
|
||||
console.log(result.topic_list);
|
||||
|
||||
_.each(result.topic_list.topics,function(ft) {
|
||||
ft.category = categories[ft.category_id];
|
||||
_.each(ft.posters,function(p) {
|
||||
|
||||
@@ -264,6 +264,7 @@ Discourse.User = Discourse.Model.extend({
|
||||
json.user.invited_by = Discourse.User.create(json.user.invited_by);
|
||||
}
|
||||
|
||||
|
||||
user.setProperties(json.user);
|
||||
return user;
|
||||
});
|
||||
|
||||
@@ -99,7 +99,11 @@ Discourse.UserAction = Discourse.Model.extend({
|
||||
}.property('target_username'),
|
||||
|
||||
targetUserUrl: Discourse.computed.url('target_username', '/users/%@'),
|
||||
userUrl: Discourse.computed.url('username', '/users/%@'),
|
||||
usernameLower: function() {
|
||||
return this.get('username').toLowerCase();
|
||||
}.property('username'),
|
||||
|
||||
userUrl: Discourse.computed.url('usernameLower', '/users/%@'),
|
||||
|
||||
postUrl: function() {
|
||||
return Discourse.Utilities.postUrl(this.get('slug'), this.get('topic_id'), this.get('post_number'));
|
||||
|
||||
@@ -18,7 +18,7 @@ Discourse.UserStream = Discourse.Model.extend({
|
||||
|
||||
findItems: function() {
|
||||
var me = this;
|
||||
if(this.get("loading")) { return; }
|
||||
if(this.get("loading")) { return Ember.RSVP.reject(); }
|
||||
this.set("loading",true);
|
||||
|
||||
var url = Discourse.getURL("/user_actions.json?offset=") + this.get('itemsLoaded') + "&username=" + (this.get('user.username_lower'));
|
||||
|
||||
@@ -47,5 +47,3 @@ Discourse.FilteredListRoute = Discourse.Route.extend({
|
||||
Discourse.ListController.filters.forEach(function(filter) {
|
||||
Discourse["List" + (filter.capitalize()) + "Route"] = Discourse.FilteredListRoute.extend({ filter: filter });
|
||||
});
|
||||
|
||||
|
||||
|
||||
119
app/assets/javascripts/discourse/routes/preferences_routes.js
Normal file
119
app/assets/javascripts/discourse/routes/preferences_routes.js
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
The common route stuff for a user's preference
|
||||
|
||||
@class PreferencesRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
The route for editing a user's "About Me" bio.
|
||||
|
||||
@class PreferencesAboutRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesAboutRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.setProperties({ model: model, newBio: model.get('bio_raw') });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
events: {
|
||||
changeAbout: function() {
|
||||
var route = this;
|
||||
var controller = route.controllerFor('preferencesAbout');
|
||||
|
||||
controller.setProperties({ saving: true });
|
||||
return controller.get('model').save().then(function() {
|
||||
controller.set('saving', false);
|
||||
route.transitionTo('user.index');
|
||||
}, function() {
|
||||
// model failed to save
|
||||
controller.set('saving', false);
|
||||
alert(I18n.t('generic_error'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
The route for editing a user's email
|
||||
|
||||
@class PreferencesEmailRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesEmailRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.setProperties({ model: model, newEmail: model.get('email') });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
The route for updating a user's username
|
||||
|
||||
@class PreferencesUsernameRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesUsernameRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
controller.setProperties({ model: user, newUsername: user.get('username') });
|
||||
}
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
This route shows who a user has invited
|
||||
|
||||
@class UserInvitedRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserInvitedRoute = Discourse.Route.extend({
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
model: function() {
|
||||
return Discourse.InviteList.findInvitedBy(this.modelFor('user'));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
Handles routes related to users.
|
||||
|
||||
@class UserRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserRoute = Discourse.Route.extend({
|
||||
|
||||
model: function(params) {
|
||||
|
||||
// If we're viewing the currently logged in user, return that object
|
||||
// instead.
|
||||
var currentUser = Discourse.User.current();
|
||||
if (currentUser && (params.username.toLowerCase() === currentUser.get('username_lower'))) {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
return Discourse.User.create({username: params.username});
|
||||
},
|
||||
|
||||
afterModel: function() {
|
||||
return this.modelFor('user').findDetails();
|
||||
},
|
||||
|
||||
serialize: function(params) {
|
||||
if (!params) return {};
|
||||
return { username: Em.get(params, 'username').toLowerCase() };
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
controller.set('model', user);
|
||||
|
||||
// Add a search context
|
||||
this.controllerFor('search').set('searchContext', user.get('searchContext'));
|
||||
},
|
||||
|
||||
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'));
|
||||
|
||||
// Remove the search context
|
||||
this.controllerFor('search').set('searchContext', null);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
192
app/assets/javascripts/discourse/routes/user_routes.js
Normal file
192
app/assets/javascripts/discourse/routes/user_routes.js
Normal file
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
Handles routes related to users.
|
||||
|
||||
@class UserRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserRoute = Discourse.Route.extend({
|
||||
|
||||
model: function(params) {
|
||||
|
||||
// If we're viewing the currently logged in user, return that object
|
||||
// instead.
|
||||
var currentUser = Discourse.User.current();
|
||||
if (currentUser && (params.username.toLowerCase() === currentUser.get('username_lower'))) {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
return Discourse.User.create({username: params.username});
|
||||
},
|
||||
|
||||
afterModel: function() {
|
||||
return this.modelFor('user').findDetails();
|
||||
},
|
||||
|
||||
serialize: function(params) {
|
||||
if (!params) return {};
|
||||
return { username: Em.get(params, 'username').toLowerCase() };
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
controller.set('model', user);
|
||||
|
||||
// Add a search context
|
||||
this.controllerFor('search').set('searchContext', user.get('searchContext'));
|
||||
},
|
||||
|
||||
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'));
|
||||
|
||||
// Remove the search context
|
||||
this.controllerFor('search').set('searchContext', null);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
This route shows who a user has invited
|
||||
|
||||
@class UserInvitedRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserInvitedRoute = Discourse.Route.extend({
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
model: function() {
|
||||
return Discourse.InviteList.findInvitedBy(this.modelFor('user'));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
The base route for showing a user's activity
|
||||
|
||||
@class UserActivityRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserActivityRoute = Discourse.Route.extend({
|
||||
renderTemplate: function() {
|
||||
this.render('user_activity', {into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
this.controllerFor('userActivity').set('model', user);
|
||||
|
||||
var composerController = this.controllerFor('composer');
|
||||
controller.set('model', user);
|
||||
if (Discourse.User.current()) {
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Discourse.UserPrivateMessagesRoute = Discourse.UserActivityRoute.extend({});
|
||||
|
||||
/**
|
||||
If we request /user/eviltrout without a sub route.
|
||||
|
||||
@class UserIndexRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserIndexRoute = Discourse.UserActivityRoute.extend({
|
||||
redirect: function() {
|
||||
this.transitionTo('userActivity', this.modelFor('user'));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
The base route for showing an activity stream.
|
||||
|
||||
@class UserActivityStreamRoute
|
||||
@extends Discourse.Route
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserActivityStreamRoute = Discourse.Route.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user').findStream(this.get('userActionType'));
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('user_stream', {into: 'user_activity', outlet: 'activity'});
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.set('model', model);
|
||||
this.controllerFor('user_activity').set('userActionType', this.get('userActionType'));
|
||||
}
|
||||
});
|
||||
|
||||
// Build all activity stream routes
|
||||
['bookmarks', 'edits', 'likes_given', 'likes_received', 'replies', 'posts', 'index'].forEach(function (userAction) {
|
||||
Discourse["UserActivity" + userAction.classify() + "Route"] = Discourse.UserActivityStreamRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES[userAction]
|
||||
});
|
||||
});
|
||||
|
||||
Discourse.UserPrivateMessagesIndexRoute = Discourse.UserActivityStreamRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES.messages_received
|
||||
});
|
||||
Discourse.UserPrivateMessagesSentRoute = Discourse.UserActivityStreamRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES.messages_sent
|
||||
});
|
||||
|
||||
//Discourse.UserTopicsListView = Em.View.extend({ templateName: 'user/topics_list' });
|
||||
Discourse.UserTopicListRoute = Discourse.Route.extend({
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('paginated_topic_list', {into: 'user_activity', outlet: 'activity'});
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
this.controllerFor('user_activity').set('userActionType', this.get('userActionType'));
|
||||
controller.set('model', model);
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.UserActivityTopicsRoute = Discourse.UserTopicListRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES.topics,
|
||||
|
||||
model: function() {
|
||||
return Discourse.TopicList.find('topics/created-by/' + this.modelFor('user').get('username_lower'));
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.UserActivityFavoritesRoute = Discourse.UserTopicListRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES.favorites,
|
||||
|
||||
model: function() {
|
||||
return Discourse.TopicList.find('favorited');
|
||||
}
|
||||
});
|
||||
@@ -1,20 +1,18 @@
|
||||
{{#with view.content}}
|
||||
<div class='row'>
|
||||
<div class='topic-meta-data span2'>
|
||||
<div class='contents'>
|
||||
<div>
|
||||
<a href='/users/{{unbound username}}'>{{avatar this imageSize="small"}}</a>
|
||||
</div>
|
||||
<h5 {{bindAttr class="staff new_user"}}><a href='{{unbound usernameUrl}}'>{{breakUp username}}</a></h5>
|
||||
<div class='row'>
|
||||
<div class='topic-meta-data span2'>
|
||||
<div class='contents'>
|
||||
<div>
|
||||
<a href='/users/{{unbound username}}'>{{avatar this imageSize="small"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class='span11 topic-body'>
|
||||
<div class="topic-meta-data-inside">
|
||||
<div class='post-info post-date'>{{unboundAgeWithTooltip created_at}}</div>
|
||||
{{#if view.previousPost}}<a href='{{unbound url}}' class="post-info arrow" title="{{i18n topic.jump_reply_up}}"><i class='icon icon-arrow-up'></i></a>{{/if}}
|
||||
</div>
|
||||
{{{unbound cooked}}}
|
||||
{{#unless view.previousPost}}<a href='{{unbound url}}' class="arrow" title="{{i18n topic.jump_reply_down}}"><i class='icon icon-arrow-down'></i></a>{{/unless}}
|
||||
<h5 {{bindAttr class="staff new_user"}}><a href='{{unbound usernameUrl}}'>{{breakUp username}}</a></h5>
|
||||
</div>
|
||||
</div>
|
||||
{{/with}}
|
||||
<div class='span11 topic-body'>
|
||||
<div class="topic-meta-data-inside">
|
||||
<div class='post-info post-date'>{{unboundAgeWithTooltip created_at}}</div>
|
||||
{{#if view.previousPost}}<a href='{{unbound url}}' class="post-info arrow" title="{{i18n topic.jump_reply_up}}"><i class='icon icon-arrow-up'></i></a>{{/if}}
|
||||
</div>
|
||||
{{{unbound cooked}}}
|
||||
{{#unless view.previousPost}}<a href='{{unbound url}}' class="arrow" title="{{i18n topic.jump_reply_down}}"><i class='icon icon-arrow-down'></i></a>{{/unless}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<div id='list-controls'>
|
||||
<div class="container">
|
||||
<ul class="nav nav-pills" id='category-filter'>
|
||||
{{each availableNavItems itemViewClass="Discourse.NavItemView"}}
|
||||
</ul>
|
||||
|
||||
{{#if canCreateTopic}}
|
||||
<button class='btn btn-default' {{action createTopic}}><i class='icon icon-plus'></i>{{createTopicText}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if canEditCategory}}
|
||||
<button class='btn btn-default' {{action editCategory category}}>{{i18n category.edit_long}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if canCreateCategory}}
|
||||
<button class='btn btn-default' {{action createCategory}}><i class='icon icon-plus'></i>{{i18n category.create}}</button>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="full-width">
|
||||
<div id='list-area'>
|
||||
{{#if loading}}
|
||||
<div class='contents loading'>
|
||||
<table id='topic-list'>
|
||||
<tr>
|
||||
<td colspan='8'>
|
||||
<div class='spinner'>{{i18n loading}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{outlet listView}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<table id="topic-list">
|
||||
<tr>
|
||||
<th>
|
||||
{{i18n topic.title}}
|
||||
</th>
|
||||
<th>{{i18n category_title}}</th>
|
||||
<th class='num posts'>{{i18n posts}}</th>
|
||||
<th class='num likes'>{{i18n likes}}</th>
|
||||
<th class='num views'>{{i18n views}}</th>
|
||||
<th class='num activity' colspan='2'>{{i18n activity}}</th>
|
||||
</tr>
|
||||
|
||||
{{#group}}
|
||||
{{#collection contentBinding="view.topics" tagName="tbody" itemTagName="tr"}}
|
||||
<td class='main-link'>
|
||||
<a class='title' href="{{unbound lastReadUrl}}">{{{unbound fancy_title}}}</a>
|
||||
{{#if unread}}
|
||||
<a href="{{unbound lastReadUrl}}" class='badge unread badge-notification' title='{{i18n topic.unread_posts count="unread"}}'>{{unbound unread}}</a>
|
||||
{{/if}}
|
||||
{{#if new_posts}}
|
||||
<a href="{{unbound lastReadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new_posts count="new_posts"}}'>{{unbound new_posts}}</a>
|
||||
{{/if}}
|
||||
{{#if unseen}}
|
||||
<a href="{{lastReadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new}}'><i class='icon icon-asterisk'></i></a>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class='category'>
|
||||
{{categoryLink category}}
|
||||
</td>
|
||||
<td class='num posts'><a href="{{lastReadUrl}}" class='badge-posts'>{{number posts_count numberKey="posts_long"}}</a></td>
|
||||
|
||||
<td class='num likes'>
|
||||
{{#if like_count}}
|
||||
<a href='{{url}}{{#if has_best_of}}?filter=best_of{{/if}}'>{{like_count}} <i class='icon-heart'></i></a>
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td {{bindAttr class=":num :views viewsHeat"}}>{{number views numberKey="views_long"}}</td>
|
||||
{{#if bumped}}
|
||||
<td class='num activity'>
|
||||
<a href="{{url}}" {{{bindAttr class=":age ageCold"}}} title='{{i18n first_post}}: {{{unboundDate created_at}}}' >{{unboundAge created_at}}</a>
|
||||
</td>
|
||||
<td class='num activity last'>
|
||||
<a href="{{lastPostUrl}}" class='age' title='{{i18n last_post}}: {{{unboundDate bumped_at}}}'>{{unboundAge bumped_at}}</a>
|
||||
</td>
|
||||
{{else}}
|
||||
<td class='num activity'>
|
||||
<a href="{{url}}" class='age' title='{{i18n first_post}}: {{{unboundDate created_at}}}'>{{unboundAge created_at}}</a>
|
||||
</td>
|
||||
<td class="activity"></td>
|
||||
{{/if}}
|
||||
{{/collection}}
|
||||
{{/group}}
|
||||
|
||||
</table>
|
||||
@@ -5,7 +5,7 @@
|
||||
</ul>
|
||||
|
||||
{{#if canCreateTopic}}
|
||||
<button class='btn btn-default' {{action createTopic}}><i class='icon icon-plus'></i>{{view.createTopicText}}</button>
|
||||
<button class='btn btn-default' {{action createTopic}}><i class='icon icon-plus'></i>{{createTopicText}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if canEditCategory}}
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<div class="full-width">
|
||||
<div id='list-area'>
|
||||
{{#if loading}}
|
||||
@@ -39,7 +38,6 @@
|
||||
{{outlet listView}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
{{#with view.content}}
|
||||
<a href='{{unbound url}}'>
|
||||
<span class='badge-category' style="background-color: #{{unbound color}}; color: #{{unbound text_color}};">{{unbound title}}</span>
|
||||
</a>
|
||||
{{/with}}
|
||||
|
||||
<a href='{{unbound url}}'>
|
||||
<span class='badge-category' style="background-color: #{{unbound color}}; color: #{{unbound text_color}};">{{unbound title}}</span>
|
||||
</a>
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
{{#with view.content}}
|
||||
<a href='{{unbound url}}'>
|
||||
{{unbound title}}
|
||||
</a>
|
||||
{{/with}}
|
||||
|
||||
<a href='{{unbound url}}'>
|
||||
{{unbound title}}
|
||||
</a>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
{{#with view.content}}
|
||||
<a href='{{unbound url}}'>
|
||||
{{avatar this usernamePath="title" imageSize="small"}}
|
||||
{{unbound title}}
|
||||
</a>
|
||||
{{/with}}
|
||||
|
||||
<a href='{{unbound url}}'>
|
||||
{{avatar this usernamePath="title" imageSize="small"}}
|
||||
{{unbound title}}
|
||||
</a>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
{{#with view.content}}
|
||||
{{#group}}
|
||||
<td class='main-link'>
|
||||
<a class='title' href="{{unbound lastReadUrl}}">{{{unbound fancy_title}}}</a>
|
||||
{{#if unread}}
|
||||
<a href="{{unbound lastReadUrl}}" class='badge unread badge-notification' title='{{i18n topic.unread_posts count="unread"}}'>{{unbound unread}}</a>
|
||||
{{/if}}
|
||||
{{#if new_posts}}
|
||||
<a href="{{unbound lastReadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new_posts count="new_posts"}}'>{{unbound new_posts}}</a>
|
||||
{{/if}}
|
||||
{{#if unseen}}
|
||||
<a href="{{lastReadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new}}'><i class='icon icon-asterisk'></i></a>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td class='category'>
|
||||
{{categoryLink category}}
|
||||
</td>
|
||||
<td class='num posts'><a href="{{lastReadUrl}}" class='badge-posts'>{{number posts_count numberKey="posts_long"}}</a></td>
|
||||
|
||||
<td class='num likes'>
|
||||
{{#if like_count}}
|
||||
<a href='{{url}}{{#if has_best_of}}?filter=best_of{{/if}}'>{{like_count}} <i class='icon-heart'></i></a>
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td {{bindAttr class=":num :views viewsHeat"}}>{{number views numberKey="views_long"}}</td>
|
||||
|
||||
{{#if bumped}}
|
||||
<td class='num activity'>
|
||||
<a href="{{url}}" {{{bindAttr class=":age ageCold"}}} title='{{i18n first_post}}: {{{unboundDate created_at}}}' >{{unboundAge created_at}}</a>
|
||||
</td>
|
||||
<td class='num activity last'>
|
||||
<a href="{{lastPostUrl}}" class='age' title='{{i18n last_post}}: {{{unboundDate bumped_at}}}'>{{unboundAge bumped_at}}</a>
|
||||
</td>
|
||||
{{else}}
|
||||
<td class='num activity'>
|
||||
<a href="{{url}}" class='age' title='{{i18n first_post}}: {{{unboundDate created_at}}}'>{{unboundAge created_at}}</a>
|
||||
</td>
|
||||
<td class="activity"></td>
|
||||
{{/if}}
|
||||
|
||||
{{/group}}
|
||||
{{/with}}
|
||||
@@ -74,24 +74,9 @@
|
||||
|
||||
{{#if details.suggested_topics.length}}
|
||||
<div id='suggested-topics'>
|
||||
|
||||
<h3>{{i18n suggested_topics.title}}</h3>
|
||||
|
||||
<div class='topics'>
|
||||
<table id="topic-list">
|
||||
<tr>
|
||||
<th>
|
||||
{{i18n topic.title}}
|
||||
</th>
|
||||
<th>{{i18n category_title}}</th>
|
||||
<th class='num posts'>{{i18n posts}}</th>
|
||||
<th class='num likes'>{{i18n likes}}</th>
|
||||
<th class='num views'>{{i18n views}}</th>
|
||||
<th class='num activity' colspan='2'>{{i18n activity}}</th>
|
||||
</tr>
|
||||
|
||||
{{each details.suggested_topics itemTagName="tr" itemViewClass="Discourse.SuggestedTopicView"}}
|
||||
</table>
|
||||
{{basicTopicList topics=details.suggested_topics}}
|
||||
</div>
|
||||
<br/>
|
||||
<h3>{{{view.browseMoreMessage}}}</h3>
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
|
||||
{{outlet activity}}
|
||||
<div id='user-activity'>
|
||||
{{outlet activity}}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
{{#with view.content}}
|
||||
<div {{bindAttr class=":item hidden deleted moderator_action"}}>
|
||||
<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>
|
||||
<span class='time'>{{date path="created_at" leaveAgo="true"}}</span>
|
||||
<span class="title">
|
||||
<a href="{{unbound postUrl}}">{{unbound title}}</a>
|
||||
</span>
|
||||
<span class="type">{{unbound descriptionHtml}}</span>
|
||||
</div>
|
||||
<p class='excerpt'>
|
||||
{{{unbound excerpt}}}
|
||||
</p>
|
||||
{{#each children}}
|
||||
<div class='child-actions'>
|
||||
<i class="icon {{unbound icon}}"></i>
|
||||
{{#each items}}
|
||||
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
<div {{bindAttr class=":item hidden deleted moderator_action"}}>
|
||||
<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>
|
||||
<span class='time'>{{date path="created_at" leaveAgo="true"}}</span>
|
||||
<span class="title">
|
||||
<a href="{{unbound postUrl}}">{{unbound title}}</a>
|
||||
</span>
|
||||
<span class="type">{{unbound descriptionHtml}}</span>
|
||||
</div>
|
||||
{{/with}}
|
||||
|
||||
<p class='excerpt'>
|
||||
{{{unbound excerpt}}}
|
||||
</p>
|
||||
{{#each children}}
|
||||
<div class='child-actions'>
|
||||
<i class="icon {{unbound icon}}"></i>
|
||||
{{#each items}}
|
||||
<a href="{{unbound userUrl}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
no
|
||||
@@ -10,6 +10,11 @@ Discourse.EmbeddedPostView = Discourse.View.extend({
|
||||
templateName: 'embedded_post',
|
||||
classNames: ['reply'],
|
||||
|
||||
init: function() {
|
||||
this._super();
|
||||
this.set('context', this.get('content'));
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
Discourse.ScreenTrack.instance().track(this.get('elementId'), this.get('post.post_number'));
|
||||
},
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
This view is used for rendering a basic list of topics.
|
||||
|
||||
@class BasicTopicListView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.BasicTopicListView = Discourse.View.extend({
|
||||
templateName: 'list/basic_topic_list'
|
||||
});
|
||||
Discourse.View.registerHelper('basicTopicList', Discourse.BasicTopicListView);
|
||||
@@ -4,34 +4,24 @@
|
||||
@class ListTopicsView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@uses Discourse.Scrolling
|
||||
@uses Discourse.LoadMore
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.ListTopicsView = Discourse.View.extend(Discourse.Scrolling, {
|
||||
Discourse.ListTopicsView = Discourse.View.extend(Discourse.LoadMore, {
|
||||
templateName: 'list/topics',
|
||||
categoryBinding: 'controller.controllers.list.category',
|
||||
canCreateTopicBinding: 'controller.controllers.list.canCreateTopic',
|
||||
listBinding: 'controller.model',
|
||||
loadedMore: false,
|
||||
currentTopicId: null,
|
||||
eyelineSelector: '.topic-list-item',
|
||||
|
||||
topicTrackingState: function() {
|
||||
return Discourse.TopicTrackingState.current();
|
||||
}.property(),
|
||||
|
||||
willDestroyElement: function() {
|
||||
this.unbindScrolling();
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
this.bindScrolling();
|
||||
var eyeline = new Discourse.Eyeline('.topic-list-item');
|
||||
|
||||
var listTopicsView = this;
|
||||
eyeline.on('sawBottom', function() {
|
||||
listTopicsView.loadMore();
|
||||
});
|
||||
|
||||
this._super();
|
||||
var scrollPos = Discourse.get('transient.topicListScrollPos');
|
||||
if (scrollPos) {
|
||||
Em.run.schedule('afterRender', function() {
|
||||
@@ -42,15 +32,10 @@ Discourse.ListTopicsView = Discourse.View.extend(Discourse.Scrolling, {
|
||||
$('html, body').scrollTop(0);
|
||||
});
|
||||
}
|
||||
this.set('eyeline', eyeline);
|
||||
},
|
||||
|
||||
showTable: function() {
|
||||
var topics = this.get('list.topics');
|
||||
if(topics) {
|
||||
return this.get('list.topics').length > 0 || this.get('topicTrackingState.hasIncoming');
|
||||
}
|
||||
}.property('list.topics.@each','topicTrackingState.hasIncoming'),
|
||||
hasTopics: Em.computed.gt('list.topics.length', 0),
|
||||
showTable: Em.computed.or('hasTopics', 'topicTrackingState.hasIncoming'),
|
||||
|
||||
updateTitle: function(){
|
||||
Discourse.notifyTitle(this.get('topicTrackingState.incomingCount'));
|
||||
@@ -76,9 +61,8 @@ Discourse.ListTopicsView = Discourse.View.extend(Discourse.Scrolling, {
|
||||
|
||||
// When the topic list is scrolled
|
||||
scrolled: function(e) {
|
||||
this._super();
|
||||
this.saveScrollPos();
|
||||
var eyeline = this.get('eyeline');
|
||||
if (eyeline) { eyeline.update(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
This view handles the rendering of a list
|
||||
|
||||
@class ListView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.ListView = Discourse.View.extend({
|
||||
templateName: 'list/list',
|
||||
composeViewBinding: Ember.Binding.oneWay('Discourse.composeView'),
|
||||
|
||||
// The window has been scrolled
|
||||
scrolled: function(e) {
|
||||
var currentView;
|
||||
currentView = this.get('container.currentView');
|
||||
return currentView ? typeof currentView.scrolled === "function" ? currentView.scrolled(e) : void 0 : void 0;
|
||||
},
|
||||
|
||||
createTopicText: function() {
|
||||
if (this.get('controller.category.name')) {
|
||||
return I18n.t("topic.create_in", {
|
||||
categoryName: this.get('controller.category.name')
|
||||
});
|
||||
} else {
|
||||
return I18n.t("topic.create");
|
||||
}
|
||||
}.property('controller.category.name')
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
This view is used for rendering a basic list of topics.
|
||||
|
||||
@class PaginatedTopicListView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@uses Discourse.LoadMore
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PaginatedTopicListView = Discourse.BasicTopicListView.extend(Discourse.LoadMore, {
|
||||
topics: Em.computed.alias('controller.model.topics'),
|
||||
classNames: ['paginated-topics-list'],
|
||||
eyelineSelector: '.paginated-topics-list #topic-list tr',
|
||||
|
||||
loadMore: function() {
|
||||
this.get('controller.model').loadMoreTopics();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -12,9 +12,7 @@ Discourse.TopicListItemView = Discourse.View.extend({
|
||||
classNameBindings: ['content.archived', ':topic-list-item', 'content.hasExcerpt:has-excerpt'],
|
||||
attributeBindings: ['data-topic-id'],
|
||||
|
||||
'data-topic-id': function() {
|
||||
return this.get('content.id');
|
||||
}.property('content.id'),
|
||||
'data-topic-id': Em.computed.alias('content.id'),
|
||||
|
||||
init: function() {
|
||||
this._super();
|
||||
|
||||
@@ -10,17 +10,14 @@ Discourse.SearchResultsTypeView = Ember.CollectionView.extend({
|
||||
tagName: 'ul',
|
||||
itemViewClass: Ember.View.extend({
|
||||
tagName: 'li',
|
||||
classNameBindings: ['selectedClass'],
|
||||
classNameBindings: ['selected'],
|
||||
templateName: Discourse.computed.fmt('parentView.type', "search/%@_result"),
|
||||
selected: Discourse.computed.propertyEqual('content.index', 'controller.selectedIndex'),
|
||||
|
||||
templateName: function() {
|
||||
return "search/" + (this.get('parentView.type')) + "_result";
|
||||
}.property('parentView.type'),
|
||||
|
||||
// Is this row currently selected by the keyboard?
|
||||
selectedClass: function() {
|
||||
if (this.get('content.index') === this.get('controller.selectedIndex')) return 'selected';
|
||||
return null;
|
||||
}.property('controller.selectedIndex')
|
||||
init: function() {
|
||||
this._super();
|
||||
this.set('context', this.get('content'));
|
||||
}
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
This view is used for rendering a suggested topic
|
||||
|
||||
@class SuggestedTopicView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.SuggestedTopicView = Discourse.View.extend({
|
||||
templateName: 'suggested_topic'
|
||||
});
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Discourse.ActivityFilterView = Discourse.View.extend({
|
||||
url: function() {
|
||||
var section = this.get('content.isPM') ? "/private-messages" : "/activity";
|
||||
return "/users/" + this.get('user.username_lower') + section + this.get('typeKey');
|
||||
}.property('typeKey'),
|
||||
}.property('typeKey', 'user.username_lower'),
|
||||
|
||||
description: function() {
|
||||
return this.get('content.description') || I18n.t("user.filters.all");
|
||||
|
||||
@@ -4,45 +4,32 @@
|
||||
@class UserStreamView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@uses Discourse.Scrolling
|
||||
@uses Discourse.LoadMore
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.UserStreamView = Ember.CollectionView.extend(Discourse.Scrolling, {
|
||||
Discourse.UserStreamView = Ember.CollectionView.extend(Discourse.LoadMore, {
|
||||
loading: false,
|
||||
elementId: 'user-stream',
|
||||
content: Em.computed.alias('controller.model.content'),
|
||||
itemViewClass: Ember.View.extend({ templateName: 'user/stream_item' }),
|
||||
eyelineSelector: '#user-activity .user-stream .item',
|
||||
classNames: ['user-stream'],
|
||||
|
||||
scrolled: function(e) {
|
||||
var eyeline = this.get('eyeline');
|
||||
if (eyeline) { eyeline.update(); }
|
||||
},
|
||||
itemViewClass: Ember.View.extend({
|
||||
templateName: 'user/stream_item',
|
||||
init: function() {
|
||||
this._super();
|
||||
this.set('context', this.get('content'));
|
||||
}
|
||||
}),
|
||||
|
||||
loadMore: function() {
|
||||
var userStreamView = this;
|
||||
if (userStreamView.get('loading')) { return; }
|
||||
|
||||
var stream = this.get('stream');
|
||||
var stream = this.get('controller.model');
|
||||
stream.findItems().then(function() {
|
||||
userStreamView.set('loading', false);
|
||||
userStreamView.get('eyeline').flushRest();
|
||||
});
|
||||
},
|
||||
|
||||
willDestroyElement: function() {
|
||||
this.unbindScrolling();
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
this.bindScrolling();
|
||||
|
||||
var eyeline = new Discourse.Eyeline('#user-stream .item');
|
||||
this.set('eyeline', eyeline);
|
||||
|
||||
var userStreamView = this;
|
||||
eyeline.on('sawBottom', function() {
|
||||
userStreamView.loadMore();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
//= require ./pagedown_custom.js
|
||||
|
||||
// Stuff we need to load first
|
||||
//= require ./discourse/mixins/scrolling
|
||||
//= require_tree ./discourse/mixins
|
||||
//= require ./discourse/components/computed
|
||||
//= require ./discourse/views/view
|
||||
|
||||
Reference in New Issue
Block a user