UX: improved our footer handling

- new "show-footer" mixins
- converted most of the routes to ES6
- FIX: handling of "indexStream" in user pages

There will now be a footer on all the following pages
- /exception
- /about
- /latest
- /new
- /unread
- /starred
- /top
- /categories
- /c/:category
- /c/:category/l/latest
- /c/:category/l/new
- /c/:category/l/unread
- /c/:category/l/top
- /t/:topic/:id
- /groups/:name/members
- /user/activity
- /user/activity/topics
- /user/activity/posts
- /user/activity/replies
- /user/activity/likes-given
- /user/activity/likes-received
- /user/activity/bookmarks
- /user/activity/starred
- /user/badges
- /user/notifications
- /user/flagged-posts
- /user/deleted-posts
- /user/private-messages
- /user/private-messages/mine
- /user/private-messages/unread
- /user/invited
- /user/:username/preferences
- /faq (static pages)
- /badges
- /badges/:id/:badge
This commit is contained in:
Régis Hanol 2014-11-19 20:37:43 +01:00
parent 87cd5dbcb7
commit 0947191060
109 changed files with 460 additions and 466 deletions

View File

@ -1,4 +1,6 @@
export default Discourse.View.extend(Discourse.LoadMore, {
import LoadMore from "discourse/mixins/load-more";
export default Discourse.View.extend(LoadMore, {
loading: false,
eyelineSelector: '.admin-flags tbody tr',

View File

@ -1,4 +1,5 @@
export default Ember.Controller.extend({
showFooter: false,
styleCategory: null,
canSignUp: function() {

View File

@ -1,35 +1,21 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {
selectedUploadId: function(){
switch(this.get("selected")){
case "system":
return this.get("system_avatar_upload_id");
case "gravatar":
return this.get("gravatar_avatar_upload_id");
default:
return this.get("custom_avatar_upload_id");
switch (this.get("selected")) {
case "system": return this.get("system_avatar_upload_id");
case "gravatar": return this.get("gravatar_avatar_upload_id");
default: return this.get("custom_avatar_upload_id");
}
}.property(
'selected',
'system_avatar_upload_id',
'gravatar_avatar_upload_id',
'custom_avatar_upload_id'),
}.property('selected', 'system_avatar_upload_id', 'gravatar_avatar_upload_id', 'custom_avatar_upload_id'),
actions: {
useUploadedAvatar: function() {
this.set("selected", "uploaded");
},
useGravatar: function() {
this.set("selected", "gravatar");
},
useSystem: function() {
this.set("selected", "system");
},
refreshGravatar: function(){
useUploadedAvatar: function() { this.set("selected", "uploaded"); },
useGravatar: function() { this.set("selected", "gravatar"); },
useSystem: function() { this.set("selected", "system"); },
refreshGravatar: function() {
var self = this;
self.set("gravatarRefreshDisabled", true);
Discourse
@ -40,4 +26,5 @@ export default DiscourseController.extend(ModalFunctionality, {
});
}
}
});

View File

@ -9,6 +9,7 @@ import ObjectController from 'discourse/controllers/object';
@module Discourse
**/
export default ObjectController.extend({
needs: ["application"],
actions: {
loadMore: function() {
@ -36,14 +37,17 @@ export default ObjectController.extend({
}.property("userBadges"),
canLoadMore: function() {
if(this.get('noMoreBadges')) {
return false;
}
if (this.get('noMoreBadges')) { return false; }
if (this.get('userBadges')) {
return this.get('model.grant_count') > this.get('userBadges.length');
} else {
return false;
}
}.property('noMoreBadges', 'model.grant_count', 'userBadges.length')
}.property('noMoreBadges', 'model.grant_count', 'userBadges.length'),
_showFooter: function() {
this.set("controllers.application.showFooter", !this.get("canLoadMore"));
}.observes("canLoadMore")
});

View File

@ -1,14 +1,6 @@
/**
Support for changing the notification level of various topics
@class BulkNotificationLevelControler
@extends Ember.Controller
@namespace Discourse
@module Discourse
**/
// Support for changing the notification level of various topics
export default Em.Controller.extend({
needs: ['topic-bulk-actions'],
notificationLevelId: null,
notificationLevels: function() {

View File

@ -1,16 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
Modal related to changing the ownership of posts
@class ChangeOwnerController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// Modal related to changing the ownership of posts
export default ObjectController.extend(Discourse.SelectedPostsCount, ModalFunctionality, {
needs: ['topic'],

View File

@ -1,11 +1,4 @@
/**
A controller for displaying messages as the user composes a message.
@class ComposerMessagesController
@extends Ember.ArrayController
@namespace Discourse
@module Discourse
**/
// A controller for displaying messages as the user composes a message.
export default Ember.ArrayController.extend({
needs: ['composer'],

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {

View File

@ -2,7 +2,7 @@ import ObjectController from 'discourse/controllers/object';
import TopPeriod from 'discourse/models/top-period';
export default ObjectController.extend({
needs: ['navigation/category', 'discovery/topics'],
needs: ['navigation/category', 'discovery/topics', 'application'],
loading: false,
category: Em.computed.alias('controllers.navigation/category.category'),
@ -10,6 +10,10 @@ export default ObjectController.extend({
loadedAllItems: Em.computed.not("controllers.discovery/topics.canLoadMore"),
_showFooter: function() {
this.set("controllers.application.showFooter", this.get("loadedAllItems"));
}.observes("loadedAllItems"),
showMoreUrl: function(period) {
var url = '', category = this.get('category');
if (category) {

View File

@ -1,16 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
Modal for editing / creating a category
@class EditCategoryController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// Modal for editing / creating a category
export default ObjectController.extend(ModalFunctionality, {
foregroundColors: ['FFFFFF', '000000'],
categoryUploadUrl: '/category/uploads',

View File

@ -1,15 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
Modal related to auto closing of topics
@class EditTopicAutoCloseController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// Modal related to auto closing of topics
export default ObjectController.extend(ModalFunctionality, {
auto_close_valid: true,
auto_close_invalid: Em.computed.not('auto_close_valid'),

View File

@ -1,6 +1,5 @@
import ObjectController from 'discourse/controllers/object';
var ButtonBackBright = {
classes: "btn-primary",
action: "back",
@ -22,14 +21,7 @@ var ButtonBackBright = {
key: "errors.buttons.fixed"
};
/**
The controller for the nice error page
@class ExceptionController
@extends ObjectController
@namespace Discourse
@module Discourse
**/
// The controller for the nice error page
export default ObjectController.extend({
thrown: null,
lastTransition: null,

View File

@ -1,13 +1,6 @@
import ObjectController from 'discourse/controllers/object';
/**
Supports logic for flags in the modal
@class FlagActionTypeController
@extends ObjectController
@namespace Discourse
@module Discourse
**/
// Supports logic for flags in the modal
export default ObjectController.extend({
needs: ['flag'],

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {

View File

@ -1,13 +1,6 @@
import ObjectController from 'discourse/controllers/object';
/**
The basic controller for a group
@class GroupController
@extends ObjectController
@namespace Discourse
@module Discourse
**/
// The basic controller for a group
export default ObjectController.extend({
counts: null,

View File

@ -1,16 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
This controller handles displaying of history
@class HistoryController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// This controller handles displaying of history
export default ObjectController.extend(ModalFunctionality, {
loading: true,
viewMode: "side_by_side",

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
export default ObjectController.extend(ModalFunctionality, {

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
export default ObjectController.extend(ModalFunctionality, {

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {

View File

@ -1,16 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
Modal related to merging of topics
@class MergeTopicController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// Modal related to merging of topics
export default ObjectController.extend(Discourse.SelectedPostsCount, ModalFunctionality, {
needs: ['topic'],

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {

View File

@ -1,16 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
This controller handles displaying of raw email
@class RawEmailController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// This controller handles displaying of raw email
export default ObjectController.extend(ModalFunctionality, {
rawEmail: "",

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {

View File

@ -1,16 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import ObjectController from 'discourse/controllers/object';
/**
Modal related to auto closing of topics
@class SplitTopicController
@extends ObjectController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// Modal related to auto closing of topics
export default ObjectController.extend(Discourse.SelectedPostsCount, ModalFunctionality, {
needs: ['topic'],

View File

@ -1,13 +1,6 @@
import ObjectController from 'discourse/controllers/object';
/**
This controller supports the admin menu on topics
@class TopicAdminMenuController
@extends ObjectController
@namespace Discourse
@module Discourse
**/
// This controller supports the admin menu on topics
export default ObjectController.extend({
menuVisible: false,
showRecover: Em.computed.and('deleted', 'details.can_recover'),

View File

@ -1,14 +1,6 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
/**
Modal for performing bulk actions on topics
@class TopicBulkActionsController
@extends Ember.ArrayController
@namespace Discourse
@uses ModalFunctionality
@module Discourse
**/
// Modal for performing bulk actions on topics
export default Ember.ArrayController.extend(ModalFunctionality, {
needs: ['discovery/topics'],

View File

@ -1,13 +1,6 @@
import ObjectController from 'discourse/controllers/object';
/**
Handles displaying of a topic as a list item
@class TopicListItemController
@extends ObjectController
@namespace Discourse
@module Discourse
**/
// Handles displaying of a topic as a list item
export default Ember.ObjectController.extend({
needs: ['discovery/topics'],

View File

@ -3,7 +3,7 @@ import { spinnerHTML } from 'discourse/helpers/loading-spinner';
export default ObjectController.extend(Discourse.SelectedPostsCount, {
multiSelect: false,
needs: ['header', 'modal', 'composer', 'quote-button', 'search', 'topic-progress'],
needs: ['header', 'modal', 'composer', 'quote-button', 'search', 'topic-progress', 'application'],
allPostsSelected: false,
editingTopic: false,
selectedPosts: null,
@ -697,6 +697,10 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
if (lastLoadedPost && lastLoadedPost === post) {
postStream.appendMore();
}
}
},
_showFooter: function() {
this.set("controllers.application.showFooter", this.get("postStream.loadedAllPosts"));
}.observes("postStream.loadedAllPosts")
});

View File

@ -1,5 +1,4 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import DiscourseController from 'discourse/controllers/controller';
export default DiscourseController.extend(ModalFunctionality, {

View File

@ -1 +1,15 @@
export default Ember.ObjectController.extend();
export default Ember.ObjectController.extend({
needs: ["application"],
_showFooter: function() {
var showFooter;
if (this.get("userActionType")) {
var stat = _.find(this.get("stats"), { action_type: this.get("userActionType") });
showFooter = stat && stat.count <= this.get("stream.itemsLoaded");
} else {
showFooter = this.get("statsCountNonPM") <= this.get("stream.itemsLoaded");
}
this.set("controllers.application.showFooter", showFooter);
}.observes("userActionType", "stream.itemsLoaded")
});

View File

@ -1,11 +1,4 @@
/**
This controller handles actions related to a user's invitations
@class UserInvitedController
@extends Ember.ArrayController
@namespace Discourse
@module Discourse
**/
// This controller handles actions related to a user's invitations
export default Ember.ObjectController.extend({
user: null,
model: null,

View File

@ -1,9 +1,12 @@
export default Ember.ArrayController.extend({
needs: ['user-notifications'],
canLoadMore: true,
needs: ['user-notifications', 'application'],
loading: false,
_showFooter: function() {
this.set("controllers.application.showFooter", !this.get("canLoadMore"));
}.observes("canLoadMore"),
showDismissButton: function() {
return this.get('user').total_unread_notifications > 0;
}.property('user'),

View File

@ -0,0 +1,7 @@
export default Ember.ObjectController.extend({
needs: ["application"],
_showFooter: function() {
this.set("controllers.application.showFooter", !this.get("canLoadMore"))
}.observes("canLoadMore")
});

View File

@ -1,17 +1,15 @@
import ObjectController from 'discourse/controllers/object';
/**
Lists of topics on a user's page.
@class UserTopicsListController
@extends ObjectController
@namespace Discourse
@module Discourse
**/
// Lists of topics on a user's page.
export default ObjectController.extend({
needs: ["application"],
hideCategory: false,
showParticipants: false,
_showFooter: function() {
this.set("controllers.application.showFooter", !this.get("canLoadMore"));
}.observes("canLoadMore"),
actions: {
loadMore: function() {
this.get('model').loadMore();

View File

@ -2,7 +2,7 @@ import ObjectController from 'discourse/controllers/object';
import CanCheckEmails from 'discourse/mixins/can-check-emails';
export default ObjectController.extend(CanCheckEmails, {
indexStream: true,
indexStream: false,
needs: ['user-notifications', 'user_topics_list'],
viewingSelf: function() {
@ -42,27 +42,6 @@ export default ObjectController.extend(CanCheckEmails, {
return this.get('can_be_deleted') && this.get('can_delete_all_posts');
}.property('can_be_deleted', 'can_delete_all_posts'),
loadedAllItems: function() {
switch (this.get("datasource")) {
case "badges": { return true; }
case "notifications": { return !this.get("controllers.user-notifications.canLoadMore"); }
case "topic_list": { return !this.get("controllers.user_topics_list.canLoadMore"); }
case "stream": {
if (this.get("userActionType")) {
var stat = _.find(this.get("stats"), { action_type: this.get("userActionType") });
return stat && stat.count <= this.get("stream.itemsLoaded");
} else {
return this.get("statsCountNonPM") <= this.get("stream.itemsLoaded");
}
}
}
return false;
}.property("datasource",
"userActionType", "stats", "stream.itemsLoaded",
"controllers.user_topics_list.canLoadMore",
"controllers.user-notifications.canLoadMore"),
privateMessagesActive: Em.computed.equal('pmView', 'index'),
privateMessagesMineActive: Em.computed.equal('pmView', 'mine'),
privateMessagesUnreadActive: Em.computed.equal('pmView', 'unread'),

View File

@ -22,8 +22,10 @@ export default {
Discourse.DiscoveryTopRoute = buildTopicRoute('top', {
actions: {
willTransition: function() {
this._super();
Discourse.User.currentProp("should_be_redirected_to_top", false);
Discourse.User.currentProp("redirected_to_top_reason", null);
return true;
}
}
});

View File

@ -1,3 +1,5 @@
import ShowFooter from "discourse/mixins/show-footer";
var configs = {
'faq': 'faq_url',
'tos': 'tos_url',
@ -5,7 +7,7 @@ var configs = {
};
export default function(page) {
return Discourse.Route.extend({
return Discourse.Route.extend(ShowFooter, {
renderTemplate: function() {
this.render('static');
},

View File

@ -1,14 +1,8 @@
/**
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
Provides the ability to load more items for a view which is scrolled to the bottom.
**/
Discourse.LoadMore = Em.Mixin.create(Ember.ViewTargetActionSupport, Discourse.Scrolling, {
export default Em.Mixin.create(Ember.ViewTargetActionSupport, Discourse.Scrolling, {
scrolled: function() {
var eyeline = this.get('eyeline');

View File

@ -0,0 +1,16 @@
export default Em.Mixin.create({
actions: {
didTransition: function() {
var self = this;
Em.run.schedule("afterRender", function() {
self.controllerFor("application").set("showFooter", true);
});
return true;
},
willTransition: function() {
this.controllerFor("application").set("showFooter", false);
return true;
}
}
})

View File

@ -12,6 +12,7 @@ Discourse.UserPostsStream = Discourse.Model.extend({
_initialize: function () {
this.setProperties({
itemsLoaded: 0,
canLoadMore: true,
content: []
});
}.on("init"),
@ -24,6 +25,7 @@ Discourse.UserPostsStream = Discourse.Model.extend({
this.setProperties({
filter: filter,
itemsLoaded: 0,
canLoadMore: true,
content: []
});
@ -32,7 +34,7 @@ Discourse.UserPostsStream = Discourse.Model.extend({
findItems: function () {
var self = this;
if (this.get("loading")) { return Ember.RSVP.reject(); }
if (this.get("loading") || !this.get("canLoadMore")) { return Ember.RSVP.reject(); }
this.set("loading", true);
@ -42,7 +44,8 @@ Discourse.UserPostsStream = Discourse.Model.extend({
self.get("content").pushObjects(posts);
self.setProperties({
loaded: true,
itemsLoaded: self.get("itemsLoaded") + posts.length
itemsLoaded: self.get("itemsLoaded") + posts.length,
canLoadMore: posts.length === 0 || posts.length < 60
});
}
}).finally(function () {

View File

@ -1,4 +1,6 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
model: function() {
return Discourse.ajax("/about.json").then(function(result) {
return result.about;

View File

@ -51,7 +51,6 @@ Discourse.Route.buildRoutes(function() {
this.route('categoryNone', { path: '/c/:slug/none' });
this.route('category', { path: '/c/:parentSlug/:slug' });
// homepage
this.route(Discourse.Utilities.defaultHomepage(), { path: '/' });
});

View File

@ -1,4 +1,6 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
model: function() {
if (PreloadStore.get('badges')) {
return PreloadStore.getAndRemove('badges').then(function(json) {

View File

@ -1,4 +1,13 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
actions: {
didTransition: function() {
this.controllerFor("badges/show")._showFooter();
return true;
}
},
serialize: function(model) {
return {id: model.get('id'), slug: model.get('name').replace(/[^A-Za-z0-9_]+/g, '-').toLowerCase()};
},

View File

@ -0,0 +1,32 @@
import ShowFooter from "discourse/mixins/show-footer";
export default function (filter) {
return Discourse.Route.extend(ShowFooter, {
actions: {
didTransition: function() {
this.controllerFor('user').set('indexStream', true);
this.controllerFor("user-posts")._showFooter();
return true;
}
},
model: function () {
return this.modelFor("user").get("postsStream");
},
afterModel: function () {
return this.modelFor("user").get("postsStream").filterBy(filter);
},
setupController: function(controller, model) {
// initialize "canLoadMore"
model.set("canLoadMore", model.get("itemsLoaded") === 60);
this.controllerFor("user-posts").set("model", model);
},
renderTemplate: function() {
this.render("user/posts", { into: "user" });
}
});
}

View File

@ -1,6 +1,6 @@
// A helper function to create a category route with parameters
import { queryParams, filterQueryParams } from 'discourse/routes/build-topic-route';
// A helper function to create a category route with parameters
export default function(filter, params) {
return Discourse.Route.extend({
queryParams: queryParams,

View File

@ -1,7 +1,6 @@
// A helper to build a topic route for a filter
import { queryParams } from 'discourse/controllers/discovery-sortable';
// A helper to build a topic route for a filter
export function filterQueryParams(params, defaultParams) {
var findOpts = defaultParams || {};
if (params) {

View File

@ -0,0 +1,31 @@
import UserTopicListRoute from "discourse/routes/user-topic-list";
import ShowFooter from "discourse/mixins/show-footer";
// A helper to build a user topic list route
export default function (viewName, path) {
return UserTopicListRoute.extend(ShowFooter, {
userActionType: Discourse.UserAction.TYPES.messages_received,
actions: {
didTransition: function() {
this.controllerFor("user-topics-list")._showFooter();
return true;
}
},
model: function() {
return Discourse.TopicList.find('topics/' + path + '/' + this.modelFor('user').get('username_lower'));
},
setupController: function() {
this._super.apply(this, arguments);
this.controllerFor('user_topics_list').setProperties({
hideCategory: true,
showParticipants: true
});
this.controllerFor('user').set("pmView", viewName);
}
});
}

View File

@ -1,20 +0,0 @@
/**
A base route that allows us to redirect when access is restricted
@class RestrictedUserRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.RestrictedUserRoute = Discourse.Route.extend({
afterModel: function() {
var user = this.modelFor('user');
if (!user.get('can_edit')) {
this.replaceWith('userActivity');
}
}
});

View File

@ -1,4 +1,6 @@
Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend(Discourse.OpenComposer, {
import ShowFooter from "discourse/mixins/show-footer";
Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend(Discourse.OpenComposer, ShowFooter, {
renderTemplate: function() {
this.render('navigation/categories', { outlet: 'navigation-bar' });
this.render('discovery/categories', { outlet: 'list-container' });
@ -58,3 +60,5 @@ Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend(Discourse.OpenCompos
}
}
});
export default Discourse.DiscoveryCategoriesRoute;

View File

@ -1,13 +1,11 @@
/**
The parent route for all discovery routes. Handles the logic for showing
the loading spinners.
@class DiscoveryRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
The parent route for all discovery routes.
Handles the logic for showing the loading spinners.
**/
Discourse.DiscoveryRoute = Discourse.Route.extend(Discourse.ScrollTop, Discourse.OpenComposer, {
import ShowFooter from "discourse/mixins/show-footer";
Discourse.DiscoveryRoute = Discourse.Route.extend(Discourse.ScrollTop, Discourse.OpenComposer, ShowFooter, {
redirect: function() { return this.redirectIfLoginRequired(); },
beforeModel: function(transition) {
@ -20,24 +18,21 @@ Discourse.DiscoveryRoute = Discourse.Route.extend(Discourse.ScrollTop, Discourse
actions: {
loading: function() {
var controller = this.controllerFor('discovery');
// If we're already loading don't do anything
if (controller.get('loading')) { return; }
controller.set('loading', true);
this.controllerFor('discovery').set("loading", true);
return true;
},
loadingComplete: function() {
var controller = this.controllerFor('discovery');
controller.set('loading', false);
this.controllerFor('discovery').set('loading', false);
if (!Discourse.Session.currentProp('topicListScrollPosition')) {
this._scrollTop();
}
},
didTransition: function() {
this.controllerFor("discovery")._showFooter();
this.send('loadingComplete');
return true;
},
// clear a pinned topic
@ -65,3 +60,4 @@ Discourse.DiscoveryRoute = Discourse.Route.extend(Discourse.ScrollTop, Discourse
});
export default Discourse.DiscoveryRoute;

View File

@ -1,4 +1,6 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
serialize: function() {
return "";
}

View File

@ -1,4 +1,12 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
actions: {
didTransition: function() {
return true;
}
},
model: function() {
return this.modelFor('group').findPosts();
},

View File

@ -1,4 +1,6 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
model: function() {
return this.modelFor('group');
},

View File

@ -1,4 +1,6 @@
export default Discourse.RestrictedUserRoute.extend({
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend({
model: function() {
return this.modelFor('user');
},
@ -35,4 +37,3 @@ export default Discourse.RestrictedUserRoute.extend({
}
});

View File

@ -1,4 +1,6 @@
export default Discourse.RestrictedUserRoute.extend({
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend({
model: function() {
return Discourse.UserBadge.findByUsername(this.modelFor('user').get('username'));
},

View File

@ -1,4 +1,6 @@
export default Discourse.RestrictedUserRoute.extend({
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend({
model: function() {
return Discourse.UserBadge.findByUsername(this.modelFor('user').get('username'));
},

View File

@ -1,4 +1,6 @@
export default Discourse.RestrictedUserRoute.extend({
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend({
model: function() {
return this.modelFor('user');
},

View File

@ -1,4 +1,6 @@
export default Discourse.RestrictedUserRoute.extend({
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend({
renderTemplate: function() {
this.render('preferences', { into: 'user', controller: 'preferences' });
}

View File

@ -1,4 +1,6 @@
export default Discourse.RestrictedUserRoute.extend({
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend({
model: function() {
return this.modelFor('user');
},

View File

@ -1,16 +1,19 @@
export default Discourse.RestrictedUserRoute.extend({
import ShowFooter from "discourse/mixins/show-footer";
import RestrictedUserRoute from "discourse/routes/restricted-user";
export default RestrictedUserRoute.extend(ShowFooter, {
model: function() {
return this.modelFor('user');
},
setupController: function(controller, user) {
controller.setProperties({ model: user, newNameInput: user.get('name') });
this.controllerFor('user').set('indexStream', false);
},
actions: {
showAvatarSelector: function() {
Discourse.Route.showModal(this, 'avatar-selector');
// all the properties needed for displaying the avatar selector modal
var controller = this.controllerFor('avatar-selector');
var user = this.modelFor('user');
@ -22,7 +25,7 @@ export default Discourse.RestrictedUserRoute.extend({
'custom_avatar_upload_id'
);
switch(props.uploaded_avatar_id){
switch (props.uploaded_avatar_id) {
case props.system_avatar_upload_id:
props.selected = "system";
break;
@ -40,7 +43,6 @@ export default Discourse.RestrictedUserRoute.extend({
var user = this.modelFor('user');
var avatarSelector = this.controllerFor('avatar-selector');
// sends the information to the server if it has changed
if (avatarSelector.get('selectedUploadId') !== user.get('uploaded_avatar_id')) {
user.pickAvatar(avatarSelector.get('selectedUploadId'));

View File

@ -0,0 +1,12 @@
// A base route that allows us to redirect when access is restricted
export default Discourse.Route.extend({
afterModel: function() {
var user = this.modelFor('user');
if (!user.get('can_edit')) {
this.replaceWith('userActivity');
}
}
});

View File

@ -0,0 +1,3 @@
import TopicFromParamsRoute from "discourse/routes/topic-from-params";
export default TopicFromParamsRoute;

View File

@ -1,12 +1,6 @@
/**
This route is used for retrieving a topic based on params
// This route is used for retrieving a topic based on params
@class TopicFromParamsRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.TopicFromParamsRoute = Discourse.Route.extend({
export default Discourse.Route.extend({
setupController: function(controller, params) {
params = params || {};
@ -56,6 +50,3 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
}
});
Discourse.TopicFromParamsNearRoute = Discourse.TopicFromParamsRoute;

View File

@ -3,7 +3,9 @@ var isTransitioning = false,
lastScrollPos = null,
SCROLL_DELAY = 500;
Discourse.TopicRoute = Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
Discourse.TopicRoute = Discourse.Route.extend(ShowFooter, {
redirect: function() { return this.redirectIfLoginRequired(); },
queryParams: {
@ -108,7 +110,13 @@ Discourse.TopicRoute = Discourse.Route.extend({
}
},
didTransition: function() {
this.controllerFor("topic")._showFooter();
return true;
},
willTransition: function() {
this._super();
this.controllerFor("quote-button").deselectText();
Em.run.cancel(scheduledReplace);
isTransitioning = true;
@ -228,3 +236,4 @@ Discourse.TopicRoute = Discourse.Route.extend({
});
RSVP.EventTarget.mixin(Discourse.TopicRoute);
export default Discourse.TopicRoute;

View File

@ -0,0 +1,5 @@
export default Discourse.Route.extend({
model: function() {
return Discourse.ajax("/404-body", { dataType: 'html' });
}
});

View File

@ -1,5 +0,0 @@
Discourse.UnknownRoute = Discourse.Route.extend({
model: function() {
return Discourse.ajax("/404-body", {dataType: 'html'});
}
});

View File

@ -0,0 +1,5 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES["bookmarks"]
});

View File

@ -0,0 +1,5 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES["edits"]
});

View File

@ -0,0 +1,14 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: undefined,
actions: {
didTransition: function() {
this._super();
this.controllerFor('user').set('indexStream', true);
return true;
}
}
});

View File

@ -0,0 +1,5 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES["likes_given"]
});

View File

@ -0,0 +1,5 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES["likes_received"]
});

View File

@ -0,0 +1,5 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES["posts"]
});

View File

@ -0,0 +1,5 @@
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
export default UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES["replies"]
});

View File

@ -0,0 +1,9 @@
import UserTopicListRoute from "discourse/routes/user-topic-list";
export default UserTopicListRoute.extend({
userActionType: Discourse.UserAction.TYPES.starred,
model: function() {
return Discourse.TopicList.find('starred', { user_id: this.modelFor('user').get('id') });
}
});

View File

@ -1,4 +1,6 @@
var UserActivityStreamRoute = Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
model: function() {
return this.modelFor('user').get('stream');
},
@ -13,16 +15,16 @@ var UserActivityStreamRoute = Discourse.Route.extend({
setupController: function(controller, model) {
controller.set('model', model);
this.controllerFor('user_activity').set('userActionType', this.get('userActionType'));
this.controllerFor('user').setProperties({
indexStream: !this.get('userActionType'),
datasource: "stream"
});
this.controllerFor('user-activity').set('userActionType', this.get('userActionType'));
},
actions: {
didTransition: function() {
this.controllerFor("user-activity")._showFooter();
return true;
},
removeBookmark: function(userAction) {
var self = this;
Discourse.Post.bookmark(userAction.get('post_id'), false)
@ -40,10 +42,3 @@ var UserActivityStreamRoute = Discourse.Route.extend({
}
});
// Build all activity stream routes
['bookmarks', 'edits', 'likes_given', 'likes_received', 'replies', 'posts', 'index'].forEach(function (userAction) {
Discourse["UserActivity" + userAction.classify() + "Route"] = UserActivityStreamRoute.extend({
userActionType: Discourse.UserAction.TYPES[userAction]
});
});

View File

@ -0,0 +1,9 @@
import UserTopicListRoute from "discourse/routes/user-topic-list";
export default UserTopicListRoute.extend({
userActionType: Discourse.UserAction.TYPES.topics,
model: function() {
return Discourse.TopicList.find('topics/created-by/' + this.modelFor('user').get('username_lower'));
}
});

View File

@ -5,7 +5,6 @@ export default Discourse.Route.extend({
setupController: function(controller, user) {
this.controllerFor('user-activity').set('model', user);
this.controllerFor('user').set('pmView', null);
// Bring up a draft
var composerController = this.controllerFor('composer');

View File

@ -1,14 +1,11 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
model: function() {
return Discourse.UserBadge.findByUsername(this.modelFor('user').get('username_lower'), {grouped: true});
},
setupController: function(controller, model) {
this.controllerFor('user').setProperties({
indexStream: false,
datasource: "badges",
});
if (this.controllerFor('user_activity').get('content')) {
this.controllerFor('user_activity').set('userActionType', -1);
}

View File

@ -0,0 +1,3 @@
import createAdminUserPostsRoute from "discourse/routes/build-admin-user-posts-route";
export default createAdminUserPostsRoute("deleted");

View File

@ -0,0 +1,3 @@
import createAdminUserPostsRoute from "discourse/routes/build-admin-user-posts-route";
export default createAdminUserPostsRoute("flagged");

View File

@ -1,8 +1,7 @@
export default Discourse.Route.extend({
beforeModel: function() {
this.controllerFor('user').set('indexStream', true);
return this.replaceWith('userActivity');
this.replaceWith('userActivity');
}
});

View File

@ -1,4 +1,6 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
renderTemplate: function() {
this.render({ into: 'user' });
},
@ -14,7 +16,6 @@ export default Discourse.Route.extend({
searchTerm: '',
totalInvites: model.invites.length
});
this.controllerFor('user').set('indexStream', false);
},
actions: {

View File

@ -1,21 +1,28 @@
export default Discourse.Route.extend({
import ShowFooter from "discourse/mixins/show-footer";
export default Discourse.Route.extend(ShowFooter, {
actions: {
didTransition: function() {
this.controllerFor("user_notifications")._showFooter();
return true;
}
},
model: function() {
var user = this.modelFor('user');
return Discourse.NotificationContainer.loadHistory(undefined, user.get('username'));
},
setupController: function(controller, model) {
this.controllerFor('user').setProperties({
indexStream: false,
datasource: "notifications"
});
controller.set('model', model);
controller.set('user', this.modelFor('user'));
if (this.controllerFor('user_activity').get('content')) {
this.controllerFor('user_activity').set('userActionType', -1);
}
controller.set('model', model);
controller.set('user', this.modelFor('user'));
// properly initialize "canLoadMore"
controller.set("canLoadMore", model.get("length") === 60);
},
renderTemplate: function() {

View File

@ -0,0 +1,3 @@
import createPMRoute from "discourse/routes/build-user-topic-list-route";
export default createPMRoute('index', 'private-messages');

View File

@ -0,0 +1,3 @@
import createPMRoute from "discourse/routes/build-user-topic-list-route";
export default createPMRoute('mine', 'private-messages-sent');

View File

@ -0,0 +1,3 @@
import createPMRoute from "discourse/routes/build-user-topic-list-route";
export default createPMRoute('unread', 'private-messages-unread');

View File

@ -1,3 +1,11 @@
import UserActivityRoute from 'discourse/routes/user-activity';
export default UserActivityRoute.extend();
export default UserActivityRoute.extend({
actions: {
willTransition: function() {
this._super();
this.controllerFor('user').set('pmView', null);
return true;
}
}
});

View File

@ -0,0 +1,14 @@
export default Discourse.Route.extend({
renderTemplate: function() {
this.render('user_topics_list');
},
setupController: function(controller, model) {
this.controllerFor('user-activity').set('userActionType', this.get('userActionType'));
this.controllerFor('user-topics-list').setProperties({
model: model,
hideCategory: false,
showParticipants: false
});
}
});

View File

@ -1,3 +1,5 @@
var INDEX_STREAM_ROUTES = ["user.deletedPosts", "user.flaggedPosts", "userActivity.index"];
export default Discourse.Route.extend({
titleToken: function() {
@ -21,12 +23,19 @@ export default Discourse.Route.extend({
archetypeId: 'private_message',
draftKey: 'new_private_message'
});
},
willTransition: function(transition) {
// will reset the indexStream when transitioning to routes that aren't "indexStream"
// otherwise the "header" will jump
var isIndexStream = ~INDEX_STREAM_ROUTES.indexOf(transition.targetName);
this.controllerFor('user').set('indexStream', isIndexStream);
return true;
}
},
model: function(params) {
// If we're viewing the currently logged in user, return that object
// instead.
// 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;

View File

@ -1,23 +0,0 @@
function createAdminPostRoute (filter) {
return Discourse.Route.extend({
model: function () {
return this.modelFor("user").get("postsStream");
},
afterModel: function () {
return this.modelFor("user").get("postsStream").filterBy(filter);
},
setupController: function (controller, model) {
controller.set("model", model);
this.controllerFor("user").set("indexStream", true);
},
renderTemplate: function() {
this.render("user/posts", { into: "user" });
}
});
}
Discourse.UserDeletedPostsRoute = createAdminPostRoute("deleted");
Discourse.UserFlaggedPostsRoute = createAdminPostRoute("flagged");

View File

@ -1,61 +0,0 @@
Discourse.UserTopicListRoute = Discourse.Route.extend({
renderTemplate: function() {
this.render('user_topics_list');
},
setupController: function(controller, model) {
this.controllerFor('user').setProperties({
indexStream: false,
datasource: "topic_list"
});
this.controllerFor('user-activity').set('userActionType', this.get('userActionType'));
this.controllerFor('user_topics_list').setProperties({
model: model,
hideCategory: false,
showParticipants: false
});
}
});
function createPMRoute(viewName, path) {
return Discourse.UserTopicListRoute.extend({
userActionType: Discourse.UserAction.TYPES.messages_received,
model: function() {
return Discourse.TopicList.find('topics/' + path + '/' + this.modelFor('user').get('username_lower'));
},
setupController: function() {
this._super.apply(this, arguments);
this.controllerFor('user_topics_list').setProperties({
hideCategory: true,
showParticipants: true
});
this.controllerFor('user').setProperties({
pmView: viewName,
indexStream: false,
datasource: "topic_list"
});
}
});
}
Discourse.UserPrivateMessagesIndexRoute = createPMRoute('index', 'private-messages');
Discourse.UserPrivateMessagesMineRoute = createPMRoute('mine', 'private-messages-sent');
Discourse.UserPrivateMessagesUnreadRoute = createPMRoute('unread', 'private-messages-unread');
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.UserActivityStarredRoute = Discourse.UserTopicListRoute.extend({
userActionType: Discourse.UserAction.TYPES.starred,
model: function() {
return Discourse.TopicList.find('starred', { user_id: this.modelFor('user').get('id') });
}
});

View File

@ -62,5 +62,3 @@
</section>
</div>
{{custom-html "footer"}}

View File

@ -5,6 +5,10 @@
{{render "user-card"}}
</div>
{{#if showFooter}}
{{custom-html "footer"}}
{{/if}}
{{render "modal"}}
{{render "topic-entrance"}}
{{render "composer"}}

View File

@ -19,5 +19,3 @@
</tbody>
</table>
</div>
{{custom-html "footer"}}

View File

@ -37,8 +37,5 @@
</div>
{{loading-spinner condition=canLoadMore}}
{{#unless canLoadMore}}
{{custom-html "footer"}}
{{/unless}}
{{/if}}
</div>

View File

@ -28,6 +28,3 @@
</div>
</div>
</div>
{{#if loadedAllItems}}
{{custom-html "footer"}}
{{/if}}

View File

@ -7,5 +7,3 @@
{{/if}}
</div>
</div>
{{custom-html "footer"}}

View File

@ -134,10 +134,6 @@
</div>
{{/if}}
{{#if postStream.loadedAllPosts}}
{{custom-html "footer"}}
{{/if}}
{{render "share"}}
{{#if currentUser.enable_quoting}}

View File

@ -194,7 +194,3 @@
</section>
</div>
{{#if loadedAllItems}}
{{custom-html "footer"}}
{{/if}}

Some files were not shown because too many files have changed in this diff Show More