Ember Upgrade: 1.0
This commit is contained in:
parent
01075c5e7a
commit
be0ce08cc2
|
@ -1,2 +0,0 @@
|
|||
//= require list_view.js
|
||||
//= require_tree ./admin
|
|
@ -0,0 +1,10 @@
|
|||
<%
|
||||
if Rails.env.development?
|
||||
require_asset ("development/list-view.js")
|
||||
else
|
||||
require_asset ("production/list-view.js")
|
||||
end
|
||||
|
||||
require_asset("main_include_admin.js")
|
||||
|
||||
%>
|
|
@ -46,5 +46,12 @@ Discourse.AdminDashboardController = Ember.Controller.extend({
|
|||
|
||||
updatedTimestamp: function() {
|
||||
return moment(this.get('updated_at')).format('LLL');
|
||||
}.property('updated_at')
|
||||
}.property('updated_at'),
|
||||
|
||||
actions: {
|
||||
refreshProblems: function() {
|
||||
this.loadProblems();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -24,23 +24,24 @@ Discourse.AdminEmailIndexController = Discourse.Controller.extend({
|
|||
this.set('sentTestEmail', false);
|
||||
}.observes('testEmailAddress'),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
Sends a test email to the currently entered email address
|
||||
|
||||
/**
|
||||
Sends a test email to the currently entered email address
|
||||
@method sendTestEmail
|
||||
**/
|
||||
sendTestEmail: function() {
|
||||
this.set('sentTestEmail', false);
|
||||
|
||||
@method sendTestEmail
|
||||
**/
|
||||
sendTestEmail: function() {
|
||||
this.set('sentTestEmail', false);
|
||||
|
||||
var adminEmailLogsController = this;
|
||||
Discourse.ajax("/admin/email/test", {
|
||||
type: 'POST',
|
||||
data: { email_address: this.get('testEmailAddress') }
|
||||
}).then(function () {
|
||||
adminEmailLogsController.set('sentTestEmail', true);
|
||||
});
|
||||
var adminEmailLogsController = this;
|
||||
Discourse.ajax("/admin/email/test", {
|
||||
type: 'POST',
|
||||
data: { email_address: this.get('testEmailAddress') }
|
||||
}).then(function () {
|
||||
adminEmailLogsController.set('sentTestEmail', true);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -8,14 +8,21 @@
|
|||
**/
|
||||
Discourse.AdminEmailPreviewDigestController = Discourse.ObjectController.extend({
|
||||
|
||||
refresh: function() {
|
||||
var model = this.get('model');
|
||||
var controller = this;
|
||||
controller.set('loading', true);
|
||||
Discourse.EmailPreview.findDigest(this.get('lastSeen')).then(function (email) {
|
||||
model.setProperties(email.getProperties('html_content', 'text_content'));
|
||||
controller.set('loading', false);
|
||||
});
|
||||
actions: {
|
||||
refresh: function() {
|
||||
var model = this.get('model'),
|
||||
self = this;
|
||||
|
||||
self.set('loading', true);
|
||||
Discourse.EmailPreview.findDigest(this.get('lastSeen')).then(function (email) {
|
||||
model.setProperties(email.getProperties('html_content', 'text_content'));
|
||||
self.set('loading', false);
|
||||
});
|
||||
},
|
||||
|
||||
toggleShowHtml: function() {
|
||||
this.toggleProperty('showHtml');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -8,62 +8,64 @@
|
|||
**/
|
||||
Discourse.AdminFlagsController = Ember.ArrayController.extend({
|
||||
|
||||
/**
|
||||
Clear all flags on a post
|
||||
actions: {
|
||||
/**
|
||||
Clear all flags on a post
|
||||
|
||||
@method clearFlags
|
||||
@param {Discourse.FlaggedPost} item The post whose flags we want to clear
|
||||
**/
|
||||
disagreeFlags: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.disagreeFlags().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
@method clearFlags
|
||||
@param {Discourse.FlaggedPost} item The post whose flags we want to clear
|
||||
**/
|
||||
disagreeFlags: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.disagreeFlags().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
|
||||
agreeFlags: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.agreeFlags().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
agreeFlags: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.agreeFlags().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
|
||||
deferFlags: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.deferFlags().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
deferFlags: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.deferFlags().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Deletes a post
|
||||
/**
|
||||
Deletes a post
|
||||
|
||||
@method deletePost
|
||||
@param {Discourse.FlaggedPost} item The post to delete
|
||||
**/
|
||||
deletePost: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.deletePost().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
@method deletePost
|
||||
@param {Discourse.FlaggedPost} item The post to delete
|
||||
**/
|
||||
deletePost: function(item) {
|
||||
var adminFlagsController = this;
|
||||
item.deletePost().then((function() {
|
||||
adminFlagsController.removeObject(item);
|
||||
}), function() {
|
||||
bootbox.alert(I18n.t("admin.flags.error"));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Deletes a user and all posts and topics created by that user.
|
||||
/**
|
||||
Deletes a user and all posts and topics created by that user.
|
||||
|
||||
@method deleteSpammer
|
||||
@param {Discourse.FlaggedPost} item The post to delete
|
||||
**/
|
||||
deleteSpammer: function(item) {
|
||||
item.get('user').deleteAsSpammer(function() { window.location.reload(); });
|
||||
@method deleteSpammer
|
||||
@param {Discourse.FlaggedPost} item The post to delete
|
||||
**/
|
||||
deleteSpammer: function(item) {
|
||||
item.get('user').deleteAsSpammer(function() { window.location.reload(); });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,49 +1,51 @@
|
|||
Discourse.AdminGroupsController = Ember.Controller.extend({
|
||||
itemController: 'adminGroup',
|
||||
|
||||
edit: function(group){
|
||||
this.get('model').select(group);
|
||||
group.load();
|
||||
},
|
||||
actions: {
|
||||
edit: function(group){
|
||||
this.get('model').select(group);
|
||||
group.load();
|
||||
},
|
||||
|
||||
refreshAutoGroups: function(){
|
||||
var controller = this;
|
||||
refreshAutoGroups: function(){
|
||||
var self = this;
|
||||
|
||||
this.set('refreshingAutoGroups', true);
|
||||
Discourse.ajax('/admin/groups/refresh_automatic_groups', {type: 'POST'})
|
||||
.then(function() {
|
||||
controller.set('model', Discourse.Group.findAll());
|
||||
controller.set('refreshingAutoGroups', false);
|
||||
});
|
||||
},
|
||||
self.set('refreshingAutoGroups', true);
|
||||
Discourse.ajax('/admin/groups/refresh_automatic_groups', {type: 'POST'}).then(function() {
|
||||
self.set('model', Discourse.Group.findAll());
|
||||
self.set('refreshingAutoGroups', false);
|
||||
});
|
||||
},
|
||||
|
||||
newGroup: function(){
|
||||
var group = Discourse.Group.create();
|
||||
group.set("loaded", true);
|
||||
var model = this.get("model");
|
||||
model.addObject(group);
|
||||
model.select(group);
|
||||
},
|
||||
newGroup: function(){
|
||||
var group = Discourse.Group.create();
|
||||
group.set("loaded", true);
|
||||
var model = this.get("model");
|
||||
model.addObject(group);
|
||||
model.select(group);
|
||||
},
|
||||
|
||||
save: function(group){
|
||||
if(!group.get("id")){
|
||||
group.create();
|
||||
} else {
|
||||
group.save();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function(group){
|
||||
var _this = this;
|
||||
return bootbox.confirm(I18n.t("admin.groups.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
if (result) {
|
||||
group.destroy().then(function(deleted) {
|
||||
if (deleted) {
|
||||
_this.get("model").removeObject(group);
|
||||
}
|
||||
});
|
||||
save: function(group){
|
||||
if(!group.get("id")){
|
||||
group.create();
|
||||
} else {
|
||||
group.save();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function(group){
|
||||
var self = this;
|
||||
return bootbox.confirm(I18n.t("admin.groups.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
if (result) {
|
||||
group.destroy().then(function(deleted) {
|
||||
if (deleted) {
|
||||
self.get("model").removeObject(group);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -4,14 +4,16 @@ Discourse.AdminReportsController = Ember.ObjectController.extend({
|
|||
viewingTable: Em.computed.equal('viewMode', 'table'),
|
||||
viewingBarChart: Em.computed.equal('viewMode', 'barChart'),
|
||||
|
||||
// Changes the current view mode to 'table'
|
||||
viewAsTable: function() {
|
||||
this.set('viewMode', 'table');
|
||||
},
|
||||
actions: {
|
||||
// Changes the current view mode to 'table'
|
||||
viewAsTable: function() {
|
||||
this.set('viewMode', 'table');
|
||||
},
|
||||
|
||||
// Changes the current view mode to 'barChart'
|
||||
viewAsBarChart: function() {
|
||||
this.set('viewMode', 'barChart');
|
||||
// Changes the current view mode to 'barChart'
|
||||
viewAsBarChart: function() {
|
||||
this.set('viewMode', 'barChart');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
|
@ -14,12 +14,15 @@ Discourse.AdminSiteContentEditController = Discourse.Controller.extend({
|
|||
return false;
|
||||
}.property('saving', 'content.content'),
|
||||
|
||||
saveChanges: function() {
|
||||
var controller = this;
|
||||
controller.setProperties({saving: true, saved: false});
|
||||
this.get('content').save().then(function () {
|
||||
controller.setProperties({saving: false, saved: true});
|
||||
});
|
||||
actions: {
|
||||
saveChanges: function() {
|
||||
var self = this;
|
||||
self.setProperties({saving: true, saved: false});
|
||||
self.get('content').save().then(function () {
|
||||
self.setProperties({saving: false, saved: true});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
Discourse.AdminSiteContentsController = Ember.ArrayController.extend({});
|
|
@ -39,35 +39,37 @@ Discourse.AdminSiteSettingsController = Ember.ArrayController.extend(Discourse.P
|
|||
});
|
||||
}.property('filter', 'content.@each', 'onlyOverridden'),
|
||||
|
||||
/**
|
||||
Reset a setting to its default value
|
||||
actions: {
|
||||
/**
|
||||
Reset a setting to its default value
|
||||
|
||||
@method resetDefault
|
||||
@param {Discourse.SiteSetting} setting The setting we want to revert
|
||||
**/
|
||||
resetDefault: function(setting) {
|
||||
setting.set('value', setting.get('default'));
|
||||
setting.save();
|
||||
},
|
||||
@method resetDefault
|
||||
@param {Discourse.SiteSetting} setting The setting we want to revert
|
||||
**/
|
||||
resetDefault: function(setting) {
|
||||
setting.set('value', setting.get('default'));
|
||||
setting.save();
|
||||
},
|
||||
|
||||
/**
|
||||
Save changes to a site setting
|
||||
/**
|
||||
Save changes to a site setting
|
||||
|
||||
@method save
|
||||
@param {Discourse.SiteSetting} setting The setting we've changed
|
||||
**/
|
||||
save: function(setting) {
|
||||
setting.save();
|
||||
},
|
||||
@method save
|
||||
@param {Discourse.SiteSetting} setting The setting we've changed
|
||||
**/
|
||||
save: function(setting) {
|
||||
setting.save();
|
||||
},
|
||||
|
||||
/**
|
||||
Cancel changes to a site setting
|
||||
/**
|
||||
Cancel changes to a site setting
|
||||
|
||||
@method cancel
|
||||
@param {Discourse.SiteSetting} setting The setting we've changed but want to revert
|
||||
**/
|
||||
cancel: function(setting) {
|
||||
setting.resetValue();
|
||||
@method cancel
|
||||
@param {Discourse.SiteSetting} setting The setting we've changed but want to revert
|
||||
**/
|
||||
cancel: function(setting) {
|
||||
setting.resetValue();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -9,22 +9,25 @@
|
|||
Discourse.AdminUserController = Discourse.ObjectController.extend({
|
||||
editingTitle: false,
|
||||
|
||||
toggleTitleEdit: function() {
|
||||
this.set('editingTitle', !this.editingTitle);
|
||||
},
|
||||
|
||||
saveTitle: function() {
|
||||
Discourse.ajax("/users/" + this.get('username').toLowerCase(), {
|
||||
data: {title: this.get('title')},
|
||||
type: 'PUT'
|
||||
}).then(null, function(e){
|
||||
bootbox.alert(I18n.t("generic_error_with_reason", {error: "http: " + e.status + " - " + e.body}));
|
||||
});
|
||||
|
||||
this.toggleTitleEdit();
|
||||
},
|
||||
|
||||
showApproval: function() {
|
||||
return Discourse.SiteSettings.must_approve_users;
|
||||
}.property()
|
||||
}.property(),
|
||||
|
||||
actions: {
|
||||
toggleTitleEdit: function() {
|
||||
this.toggleProperty('editingTitle');
|
||||
},
|
||||
|
||||
saveTitle: function() {
|
||||
Discourse.ajax("/users/" + this.get('username').toLowerCase(), {
|
||||
data: {title: this.get('title')},
|
||||
type: 'PUT'
|
||||
}).then(null, function(e){
|
||||
bootbox.alert(I18n.t("generic_error_with_reason", {error: "http: " + e.status + " - " + e.body}));
|
||||
});
|
||||
|
||||
this.send('toggleTitleEdit');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -33,7 +33,7 @@ Discourse.AdminLogsStaffActionLogsRoute = Discourse.Route.extend({
|
|||
return controller.show();
|
||||
},
|
||||
|
||||
events: {
|
||||
actions: {
|
||||
showDetailsModal: function(logRecord) {
|
||||
Discourse.Route.showModal(this, 'admin_staff_action_log_details', logRecord);
|
||||
this.controllerFor('modal').set('modalClass', 'log-details-modal');
|
||||
|
|
|
@ -13,24 +13,11 @@ Discourse.AdminSiteContentEditRoute = Discourse.Route.extend({
|
|||
},
|
||||
|
||||
model: function(params) {
|
||||
var list = this.controllerFor('adminSiteContents').get('model');
|
||||
var list = Discourse.SiteContentType.findAll();
|
||||
|
||||
// ember routing is fun ... this is what happens
|
||||
//
|
||||
// linkTo creates an Ember.LinkView , it marks an <a> with the class "active"
|
||||
// if the "context" of this dynamic route is equal to the model in the linkTo
|
||||
// the route "context" is set here, so we want to make sure we have the exact
|
||||
// same object, from Ember we have:
|
||||
//
|
||||
// if (handlerInfo.context !== object) { return false; }
|
||||
//
|
||||
// we could avoid this hack if Ember just compared .serialize(model) with .serialize(context)
|
||||
//
|
||||
// alternatively we could use some sort of identity map
|
||||
//
|
||||
// see also: https://github.com/emberjs/ember.js/issues/3005
|
||||
|
||||
return list.findProperty("content_type", params.content_type);
|
||||
return list.then(function(items) {
|
||||
return items.findProperty("content_type", params.content_type);
|
||||
});
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
<div class="full-width">
|
||||
|
||||
<ul class="nav nav-pills">
|
||||
<li>{{#linkTo 'admin.dashboard'}}{{i18n admin.dashboard.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'admin.dashboard'}}{{i18n admin.dashboard.title}}{{/link-to}}</li>
|
||||
{{#if currentUser.admin}}
|
||||
<li>{{#linkTo 'admin.site_settings'}}{{i18n admin.site_settings.title}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminSiteContents'}}{{i18n admin.site_content.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'admin.site_settings'}}{{i18n admin.site_settings.title}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminSiteContents'}}{{i18n admin.site_content.title}}{{/link-to}}</li>
|
||||
{{/if}}
|
||||
<li>{{#linkTo 'adminUsersList'}}{{i18n admin.users.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminUsersList'}}{{i18n admin.users.title}}{{/link-to}}</li>
|
||||
{{#if currentUser.admin}}
|
||||
<li>{{#linkTo 'admin.groups'}}{{i18n admin.groups.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'admin.groups'}}{{i18n admin.groups.title}}{{/link-to}}</li>
|
||||
{{/if}}
|
||||
<li>{{#linkTo 'adminEmail'}}{{i18n admin.email.title}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminFlags'}}{{i18n admin.flags.title}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminLogs'}}{{i18n admin.logs.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminEmail'}}{{i18n admin.email.title}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminFlags'}}{{i18n admin.flags.title}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminLogs'}}{{i18n admin.logs.title}}{{/link-to}}</li>
|
||||
{{#if currentUser.admin}}
|
||||
<li>{{#linkTo 'admin.customize'}}{{i18n admin.customize.title}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'admin.api'}}{{i18n admin.api.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'admin.customize'}}{{i18n admin.customize.title}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'admin.api'}}{{i18n admin.api.title}}{{/link-to}}</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</p>
|
||||
<p class="actions">
|
||||
<small>{{i18n admin.dashboard.last_checked}}: {{problemsTimestamp}}</small>
|
||||
<button {{action loadProblems}} class="btn btn-small"><i class="icon icon-refresh"></i>{{i18n admin.dashboard.refresh_problems}}</button>
|
||||
<button {{action refreshProblems}} class="btn btn-small"><i class="icon icon-refresh"></i>{{i18n admin.dashboard.refresh_problems}}</button>
|
||||
</p>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -25,7 +25,7 @@
|
|||
<div class="problem-messages">
|
||||
<p>
|
||||
{{i18n admin.dashboard.no_problems}}
|
||||
<button {{action loadProblems}} class="btn btn-small"><i class="icon icon-refresh"></i>{{i18n admin.dashboard.refresh_problems}}</button>
|
||||
<button {{action refreshProblems}} class="btn btn-small"><i class="icon icon-refresh"></i>{{i18n admin.dashboard.refresh_problems}}</button>
|
||||
</p>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
@ -121,15 +121,15 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td class="title"><i class='icon icon-trophy'></i> {{i18n admin.dashboard.admins}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.admins'}}{{admins}}{{/linkTo}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.admins'}}{{admins}}{{/link-to}}</td>
|
||||
<td class="title"><i class='icon icon-ban-circle'></i> {{i18n admin.dashboard.banned}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.banned'}}{{banned}}{{/linkTo}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.banned'}}{{banned}}{{/link-to}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title"><i class='icon icon-magic'></i> {{i18n admin.dashboard.moderators}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.moderators'}}{{moderators}}{{/linkTo}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.moderators'}}{{moderators}}{{/link-to}}</td>
|
||||
<td class="title"><i class='icon icon-ban-circle'></i> {{i18n admin.dashboard.blocked}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.blocked'}}{{blocked}}{{/linkTo}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.blocked'}}{{blocked}}{{/link-to}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -265,7 +265,7 @@
|
|||
{{#each top_referrers.data}}
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="title">{{#linkTo 'adminUser' this}}{{unbound username}}{{/linkTo}}</td>
|
||||
<td class="title">{{#link-to 'adminUser' this}}{{unbound username}}{{/link-to}}</td>
|
||||
<td class="value">{{num_clicks}}</td>
|
||||
<td class="value">{{num_topics}}</td>
|
||||
</tr>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class='admin-controls'>
|
||||
<div class='span15'>
|
||||
<ul class="nav nav-pills">
|
||||
<li>{{#linkTo 'adminEmail.index'}}{{i18n admin.email.settings}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminEmail.logs'}}{{i18n admin.email.logs}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminEmail.previewDigest'}}{{i18n admin.email.preview_digest}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminEmail.index'}}{{i18n admin.email.settings}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminEmail.logs'}}{{i18n admin.email.logs}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminEmail.previewDigest'}}{{i18n admin.email.preview_digest}}{{/link-to}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<td>{{date created_at}}</td>
|
||||
<td>
|
||||
{{#if user}}
|
||||
{{#linkTo 'adminUser' user}}{{avatar user imageSize="tiny"}}{{/linkTo}}
|
||||
{{#linkTo 'adminUser' user}}{{user.username}}{{/linkTo}}
|
||||
{{#link-to 'adminUser' user}}{{avatar user imageSize="tiny"}}{{/link-to}}
|
||||
{{#link-to 'adminUser' user}}{{user.username}}{{/link-to}}
|
||||
{{else}}
|
||||
—
|
||||
{{/if}}
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<div class="span7 toggle">
|
||||
<label>{{i18n admin.email.format}}</label>
|
||||
{{#if showHtml}}
|
||||
<span>{{i18n admin.email.html}}</span> | <a href='#' {{action toggleProperty 'showHtml'}}>{{i18n admin.email.text}}</a>
|
||||
<span>{{i18n admin.email.html}}</span> | <a href='#' {{action toggleShowHtml}}>{{i18n admin.email.text}}</a>
|
||||
{{else}}
|
||||
<a href='#' {{action toggleProperty 'showHtml'}}>{{i18n admin.email.html}}</a> | <span>{{i18n admin.email.text}}</span>
|
||||
<a href='#' {{action toggleShowHtml}}>{{i18n admin.email.html}}</a> | <span>{{i18n admin.email.text}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class='admin-controls'>
|
||||
<div class='span15'>
|
||||
<ul class="nav nav-pills">
|
||||
<li>{{#linkTo 'adminFlags.active'}}{{i18n admin.flags.active}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminFlags.old'}}{{i18n admin.flags.old}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminFlags.active'}}{{i18n admin.flags.active}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminFlags.old'}}{{i18n admin.flags.old}}{{/link-to}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -25,7 +25,7 @@
|
|||
{{#each flaggedPost in content}}
|
||||
<tr {{bindAttr class="flaggedPost.extraClasses"}}>
|
||||
|
||||
<td class='user'>{{#if flaggedPost.user}}{{#linkTo 'adminUser' flaggedPost.user}}{{avatar flaggedPost.user imageSize="small"}}{{/linkTo}}{{/if}}</td>
|
||||
<td class='user'>{{#if flaggedPost.user}}{{#link-to 'adminUser' flaggedPost.user}}{{avatar flaggedPost.user imageSize="small"}}{{/link-to}}{{/if}}</td>
|
||||
|
||||
<td class='excerpt'>{{#if flaggedPost.topicHidden}}<i title='{{i18n topic_statuses.invisible.help}}' class='icon icon-eye-close'></i> {{/if}}<h3><a href='{{unbound flaggedPost.url}}'>{{flaggedPost.title}}</a></h3><br>{{{flaggedPost.excerpt}}}
|
||||
</td>
|
||||
|
@ -35,7 +35,7 @@
|
|||
{{#each flaggedPost.flaggers}}
|
||||
<tr>
|
||||
<td>
|
||||
{{#linkTo 'adminUser' this.user}}{{avatar this.user imageSize="small"}} {{/linkTo}}
|
||||
{{#link-to 'adminUser' this.user}}{{avatar this.user imageSize="small"}} {{/link-to}}
|
||||
</td>
|
||||
<td>
|
||||
{{date this.flaggedAt}}
|
||||
|
@ -54,7 +54,7 @@
|
|||
<tr>
|
||||
<td></td>
|
||||
<td class='message'>
|
||||
<div>{{#linkTo 'adminUser' user}}{{avatar user imageSize="small"}}{{/linkTo}} {{message}} <a href="{{unbound permalink}}"><button class='btn'><i class="icon-reply"></i> {{i18n admin.flags.view_message}}</button></a></div>
|
||||
<div>{{#link-to 'adminUser' user}}{{avatar user imageSize="small"}}{{/link-to}} {{message}} <a href="{{unbound permalink}}"><button class='btn'><i class="icon-reply"></i> {{i18n admin.flags.view_message}}</button></a></div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div class='admin-controls'>
|
||||
<div class='span15'>
|
||||
<ul class="nav nav-pills">
|
||||
<li>{{#linkTo 'adminLogs.staffActionLogs'}}{{i18n admin.logs.staff_actions.title}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminLogs.screenedEmails'}}{{i18n admin.logs.screened_emails.title}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminLogs.screenedUrls'}}{{i18n admin.logs.screened_urls.title}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminLogs.staffActionLogs'}}{{i18n admin.logs.staff_actions.title}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminLogs.screenedEmails'}}{{i18n admin.logs.screened_emails.title}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminLogs.screenedUrls'}}{{i18n admin.logs.screened_urls.title}}{{/link-to}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="col value first staff_user">
|
||||
{{#linkTo 'adminUser' acting_user}}{{avatar acting_user imageSize="tiny"}}{{/linkTo}}
|
||||
{{#link-to 'adminUser' acting_user}}{{avatar acting_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action filterByStaffUser acting_user}}>{{acting_user.username}}</a>
|
||||
</div>
|
||||
<div class="col value action">
|
||||
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
<div class="col value subject">
|
||||
{{#if target_user}}
|
||||
{{#linkTo 'adminUser' target_user}}{{avatar target_user imageSize="tiny"}}{{/linkTo}}
|
||||
{{#link-to 'adminUser' target_user}}{{avatar target_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action filterByTargetUser target_user}}>{{target_user.username}}</a>
|
||||
{{/if}}
|
||||
{{#if subject}}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<tr>
|
||||
<td class="title">{{title}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.newuser'}}{{valueAtTrustLevel data 0}}{{/linkTo}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.basic'}}{{valueAtTrustLevel data 1}}{{/linkTo}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.regular'}}{{valueAtTrustLevel data 2}}{{/linkTo}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.leaders'}}{{valueAtTrustLevel data 3}}{{/linkTo}}</td>
|
||||
<td class="value">{{#linkTo 'adminUsersList.elders'}}{{valueAtTrustLevel data 4}}{{/linkTo}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.newuser'}}{{valueAtTrustLevel data 0}}{{/link-to}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.basic'}}{{valueAtTrustLevel data 1}}{{/link-to}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.regular'}}{{valueAtTrustLevel data 2}}{{/link-to}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.leaders'}}{{valueAtTrustLevel data 3}}{{/link-to}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.elders'}}{{valueAtTrustLevel data 4}}{{/link-to}}</td>
|
||||
</tr>
|
|
@ -4,7 +4,7 @@
|
|||
<ul>
|
||||
{{#each type in model}}
|
||||
<li>
|
||||
{{#linkTo 'adminSiteContentEdit' type}}{{type.title}}{{/linkTo}}
|
||||
{{#link-to 'adminSiteContentEdit' type}}{{type.title}}{{/link-to}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
<div class='field'>{{i18n user.username.title}}</div>
|
||||
<div class='value'>{{username}}</div>
|
||||
<div class='controls'>
|
||||
{{#linkTo 'userActivity' class="btn"}}
|
||||
{{#link-to 'userActivity' class="btn"}}
|
||||
<i class='icon icon-user'></i>
|
||||
{{i18n admin.user.show_public_profile}}
|
||||
{{/linkTo}}
|
||||
{{/link-to}}
|
||||
{{#if can_impersonate}}
|
||||
<button class='btn' {{action impersonate target="content"}}>
|
||||
<i class='icon icon-screenshot'></i>
|
||||
|
@ -71,8 +71,8 @@
|
|||
{{#if approved}}
|
||||
{{i18n admin.user.approved_by}}
|
||||
|
||||
{{#linkTo 'adminUser' approved_by}}{{avatar approved_by imageSize="small"}}{{/linkTo}}
|
||||
{{#linkTo 'adminUser' approved_by}}{{approved_by.username}}{{/linkTo}}
|
||||
{{#link-to 'adminUser' approved_by}}{{avatar approved_by imageSize="small"}}{{/link-to}}
|
||||
{{#link-to 'adminUser' approved_by}}{{approved_by.username}}{{/link-to}}
|
||||
{{else}}
|
||||
{{i18n no_value}}
|
||||
{{/if}}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<div class='admin-controls'>
|
||||
<div class='span15'>
|
||||
<ul class="nav nav-pills">
|
||||
<li>{{#linkTo 'adminUsersList.active'}}{{i18n admin.users.nav.active}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminUsersList.new'}}{{i18n admin.users.nav.new}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminUsersList.active'}}{{i18n admin.users.nav.active}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminUsersList.new'}}{{i18n admin.users.nav.new}}{{/link-to}}</li>
|
||||
{{#if Discourse.SiteSettings.must_approve_users}}
|
||||
<li>{{#linkTo 'adminUsersList.pending'}}{{i18n admin.users.nav.pending}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminUsersList.pending'}}{{i18n admin.users.nav.pending}}{{/link-to}}</li>
|
||||
{{/if}}
|
||||
<li>{{#linkTo 'adminUsersList.admins'}}{{i18n admin.users.nav.admins}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminUsersList.moderators'}}{{i18n admin.users.nav.moderators}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminUsersList.banned'}}{{i18n admin.users.nav.banned}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'adminUsersList.blocked'}}{{i18n admin.users.nav.blocked}}{{/linkTo}}</li>
|
||||
<li>{{#link-to 'adminUsersList.admins'}}{{i18n admin.users.nav.admins}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminUsersList.moderators'}}{{i18n admin.users.nav.moderators}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminUsersList.banned'}}{{i18n admin.users.nav.banned}}{{/link-to}}</li>
|
||||
<li>{{#link-to 'adminUsersList.blocked'}}{{i18n admin.users.nav.blocked}}{{/link-to}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='span5 username controls'>
|
||||
|
@ -61,8 +61,8 @@
|
|||
{{/if}}
|
||||
</td>
|
||||
{{/if}}
|
||||
<td>{{#linkTo 'adminUser' this}}{{avatar this imageSize="small"}}{{/linkTo}}</td>
|
||||
<td>{{#linkTo 'adminUser' this}}{{unbound username}}{{/linkTo}}</td>
|
||||
<td>{{#link-to 'adminUser' this}}{{avatar this imageSize="small"}}{{/link-to}}</td>
|
||||
<td>{{#link-to 'adminUser' this}}{{unbound username}}{{/link-to}}</td>
|
||||
<td>{{shorten email}}</td>
|
||||
<td>{{{unbound last_emailed_age}}}</td>
|
||||
<td>{{{unbound last_seen_age}}}</td>
|
||||
|
|
|
@ -13,18 +13,18 @@
|
|||
|
||||
<%
|
||||
if Rails.env.development?
|
||||
require_asset ("./external_development/jquery-2.0.3.js")
|
||||
require_asset ("development/jquery-2.0.3.js")
|
||||
else
|
||||
require_asset ("./external_production/jquery-2.0.3.min.js")
|
||||
require_asset ("production/jquery-2.0.3.min.js")
|
||||
end
|
||||
|
||||
require_asset ("./external/jquery.ui.widget.js")
|
||||
require_asset ("./external/handlebars.js")
|
||||
require_asset ("jquery.ui.widget.js")
|
||||
require_asset ("handlebars.js")
|
||||
|
||||
if Rails.env.development?
|
||||
require_asset ("./external_development/ember.js")
|
||||
require_asset ("development/ember.js")
|
||||
else
|
||||
require_asset ("./external_production/ember.js")
|
||||
require_asset ("production/ember.js")
|
||||
end
|
||||
|
||||
require_asset ("./main_include.js")
|
||||
|
|
|
@ -28,7 +28,7 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
|||
return u + url;
|
||||
},
|
||||
|
||||
resolver: Discourse.Resolver,
|
||||
Resolver: Discourse.Resolver,
|
||||
|
||||
titleChanged: function() {
|
||||
var title = "";
|
||||
|
@ -112,7 +112,7 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
|||
if ($currentTarget.attr('target')) { return; }
|
||||
if ($currentTarget.data('auto-route')) { return; }
|
||||
|
||||
// If it's an ember #linkTo skip it
|
||||
// If it's an ember #link-to skip it
|
||||
if ($currentTarget.hasClass('ember-view')) { return; }
|
||||
|
||||
if ($currentTarget.hasClass('lightbox')) { return; }
|
||||
|
|
|
@ -8,15 +8,19 @@
|
|||
@module Discourse
|
||||
**/
|
||||
Discourse.AvatarSelectorController = Discourse.Controller.extend(Discourse.ModalFunctionality, {
|
||||
useUploadedAvatar: function() {
|
||||
this.set("use_uploaded_avatar", true);
|
||||
},
|
||||
|
||||
useGravatar: function() {
|
||||
this.set("use_uploaded_avatar", false);
|
||||
actions: {
|
||||
useUploadedAvatar: function() {
|
||||
this.set("use_uploaded_avatar", true);
|
||||
},
|
||||
|
||||
useGravatar: function() {
|
||||
this.set("use_uploaded_avatar", false);
|
||||
}
|
||||
},
|
||||
|
||||
avatarTemplate: function() {
|
||||
return this.get("use_uploaded_avatar") ? this.get("uploaded_avatar_template") : this.get("gravatar_template");
|
||||
}.property("use_uploaded_avatar", "uploaded_avatar_template", "gravatar_template")
|
||||
|
||||
});
|
||||
|
|
|
@ -17,15 +17,6 @@ Discourse.ComposerController = Discourse.Controller.extend({
|
|||
this.set('similarTopics', Em.A());
|
||||
},
|
||||
|
||||
togglePreview: function() {
|
||||
this.get('model').togglePreview();
|
||||
},
|
||||
|
||||
// Import a quote from the post
|
||||
importQuote: function() {
|
||||
this.get('model').importQuote();
|
||||
},
|
||||
|
||||
updateDraftStatus: function() {
|
||||
this.get('model').updateDraftStatus();
|
||||
},
|
||||
|
@ -39,84 +30,122 @@ Discourse.ComposerController = Discourse.Controller.extend({
|
|||
return Discourse.Category.list();
|
||||
}.property(),
|
||||
|
||||
save: function(force) {
|
||||
var composer = this.get('model'),
|
||||
composerController = this;
|
||||
actions: {
|
||||
|
||||
if( composer.get('cantSubmitPost') ) {
|
||||
this.set('view.showTitleTip', Date.now());
|
||||
this.set('view.showCategoryTip', Date.now());
|
||||
this.set('view.showReplyTip', Date.now());
|
||||
return;
|
||||
}
|
||||
// Toggle the reply view
|
||||
toggle: function() {
|
||||
this.closeAutocomplete();
|
||||
switch (this.get('model.composeState')) {
|
||||
case Discourse.Composer.OPEN:
|
||||
if (this.blank('model.reply') && this.blank('model.title')) {
|
||||
this.close();
|
||||
} else {
|
||||
this.shrink();
|
||||
}
|
||||
break;
|
||||
case Discourse.Composer.DRAFT:
|
||||
this.set('model.composeState', Discourse.Composer.OPEN);
|
||||
break;
|
||||
case Discourse.Composer.SAVING:
|
||||
this.close();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
composer.set('disableDrafts', true);
|
||||
|
||||
// for now handle a very narrow use case
|
||||
// if we are replying to a topic AND not on the topic pop the window up
|
||||
if(!force && composer.get('replyingToTopic')) {
|
||||
var topic = this.get('topic');
|
||||
if (!topic || topic.get('id') !== composer.get('topic.id'))
|
||||
{
|
||||
var message = I18n.t("composer.posting_not_on_topic", {title: this.get('model.topic.title')});
|
||||
togglePreview: function() {
|
||||
this.get('model').togglePreview();
|
||||
},
|
||||
|
||||
var buttons = [{
|
||||
"label": I18n.t("composer.cancel"),
|
||||
"class": "cancel",
|
||||
"link": true
|
||||
}];
|
||||
// Import a quote from the post
|
||||
importQuote: function() {
|
||||
this.get('model').importQuote();
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this.cancelComposer();
|
||||
},
|
||||
|
||||
save: function(force) {
|
||||
var composer = this.get('model'),
|
||||
composerController = this;
|
||||
|
||||
if( composer.get('cantSubmitPost') ) {
|
||||
this.set('view.showTitleTip', Date.now());
|
||||
this.set('view.showCategoryTip', Date.now());
|
||||
this.set('view.showReplyTip', Date.now());
|
||||
return;
|
||||
}
|
||||
|
||||
composer.set('disableDrafts', true);
|
||||
|
||||
// for now handle a very narrow use case
|
||||
// if we are replying to a topic AND not on the topic pop the window up
|
||||
if(!force && composer.get('replyingToTopic')) {
|
||||
var topic = this.get('topic');
|
||||
if (!topic || topic.get('id') !== composer.get('topic.id'))
|
||||
{
|
||||
var message = I18n.t("composer.posting_not_on_topic", {title: this.get('model.topic.title')});
|
||||
|
||||
var buttons = [{
|
||||
"label": I18n.t("composer.cancel"),
|
||||
"class": "cancel",
|
||||
"link": true
|
||||
}];
|
||||
|
||||
if(topic) {
|
||||
buttons.push({
|
||||
"label": I18n.t("composer.reply_here") + "<br/><div class='topic-title overflow-ellipsis'>" + topic.get('title') + "</div>",
|
||||
"class": "btn btn-reply-here",
|
||||
"callback": function(){
|
||||
composer.set('topic', topic);
|
||||
composer.set('post', null);
|
||||
composerController.save(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(topic) {
|
||||
buttons.push({
|
||||
"label": I18n.t("composer.reply_here") + "<br/><div class='topic-title overflow-ellipsis'>" + topic.get('title') + "</div>",
|
||||
"class": "btn btn-reply-here",
|
||||
"label": I18n.t("composer.reply_original") + "<br/><div class='topic-title overflow-ellipsis'>" + this.get('model.topic.title') + "</div>",
|
||||
"class": "btn-primary btn-reply-on-original",
|
||||
"callback": function(){
|
||||
composer.set('topic', topic);
|
||||
composer.set('post', null);
|
||||
composerController.save(true);
|
||||
}
|
||||
});
|
||||
|
||||
bootbox.dialog(message, buttons, {"classes": "reply-where-modal"});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return composer.save({
|
||||
imageSizes: this.get('view').imageSizes()
|
||||
}).then(function(opts) {
|
||||
|
||||
// If we replied as a new topic successfully, remove the draft.
|
||||
if (composerController.get('replyAsNewTopicDraft')) {
|
||||
composerController.destroyDraft();
|
||||
}
|
||||
|
||||
buttons.push({
|
||||
"label": I18n.t("composer.reply_original") + "<br/><div class='topic-title overflow-ellipsis'>" + this.get('model.topic.title') + "</div>",
|
||||
"class": "btn-primary btn-reply-on-original",
|
||||
"callback": function(){
|
||||
composerController.save(true);
|
||||
}
|
||||
});
|
||||
opts = opts || {};
|
||||
composerController.close();
|
||||
|
||||
bootbox.dialog(message, buttons, {"classes": "reply-where-modal"});
|
||||
return;
|
||||
}
|
||||
var currentUser = Discourse.User.current();
|
||||
if (composer.get('creatingTopic')) {
|
||||
currentUser.set('topic_count', currentUser.get('topic_count') + 1);
|
||||
} else {
|
||||
currentUser.set('reply_count', currentUser.get('reply_count') + 1);
|
||||
}
|
||||
Discourse.URL.routeTo(opts.post.get('url'));
|
||||
|
||||
}, function(error) {
|
||||
composer.set('disableDrafts', false);
|
||||
bootbox.alert(error);
|
||||
});
|
||||
}
|
||||
|
||||
return composer.save({
|
||||
imageSizes: this.get('view').imageSizes()
|
||||
}).then(function(opts) {
|
||||
|
||||
// If we replied as a new topic successfully, remove the draft.
|
||||
if (composerController.get('replyAsNewTopicDraft')) {
|
||||
composerController.destroyDraft();
|
||||
}
|
||||
|
||||
opts = opts || {};
|
||||
composerController.close();
|
||||
|
||||
var currentUser = Discourse.User.current();
|
||||
if (composer.get('creatingTopic')) {
|
||||
currentUser.set('topic_count', currentUser.get('topic_count') + 1);
|
||||
} else {
|
||||
currentUser.set('reply_count', currentUser.get('reply_count') + 1);
|
||||
}
|
||||
Discourse.URL.routeTo(opts.post.get('url'));
|
||||
|
||||
}, function(error) {
|
||||
composer.set('disableDrafts', false);
|
||||
bootbox.alert(error);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
Checks to see if a reply has been typed. This is signaled by a keyUp
|
||||
event in a view.
|
||||
|
@ -230,7 +259,7 @@ Discourse.ComposerController = Discourse.Controller.extend({
|
|||
} else {
|
||||
opts.tested = true;
|
||||
if (!opts.ignoreIfChanged) {
|
||||
this.cancel().then(function() { composerController.open(opts); },
|
||||
this.cancelComposer().then(function() { composerController.open(opts); },
|
||||
function() { return promise.reject(); });
|
||||
}
|
||||
return promise;
|
||||
|
@ -278,7 +307,7 @@ Discourse.ComposerController = Discourse.Controller.extend({
|
|||
}
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
cancelComposer: function() {
|
||||
var composerController = this;
|
||||
|
||||
return Ember.Deferred.promise(function (promise) {
|
||||
|
@ -332,26 +361,6 @@ Discourse.ComposerController = Discourse.Controller.extend({
|
|||
$('#wmd-input').autocomplete({ cancel: true });
|
||||
},
|
||||
|
||||
// Toggle the reply view
|
||||
toggle: function() {
|
||||
this.closeAutocomplete();
|
||||
switch (this.get('model.composeState')) {
|
||||
case Discourse.Composer.OPEN:
|
||||
if (this.blank('model.reply') && this.blank('model.title')) {
|
||||
this.close();
|
||||
} else {
|
||||
this.shrink();
|
||||
}
|
||||
break;
|
||||
case Discourse.Composer.DRAFT:
|
||||
this.set('model.composeState', Discourse.Composer.OPEN);
|
||||
break;
|
||||
case Discourse.Composer.SAVING:
|
||||
this.close();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// ESC key hit
|
||||
hitEsc: function() {
|
||||
if (this.get('model.viewOpen')) {
|
||||
|
|
|
@ -20,6 +20,18 @@ Discourse.ComposerMessagesController = Ember.ArrayController.extend({
|
|||
this.reset();
|
||||
},
|
||||
|
||||
actions: {
|
||||
/**
|
||||
Closes and hides a message.
|
||||
|
||||
@method closeMessage
|
||||
@params {Object} message The message to dismiss
|
||||
**/
|
||||
closeMessage: function(message) {
|
||||
this.removeObject(message);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Displays a new message
|
||||
|
||||
|
@ -37,16 +49,6 @@ Discourse.ComposerMessagesController = Ember.ArrayController.extend({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Closes and hides a message.
|
||||
|
||||
@method closeMessage
|
||||
@params {Object} message The message to dismiss
|
||||
**/
|
||||
closeMessage: function(message) {
|
||||
this.removeObject(message);
|
||||
},
|
||||
|
||||
/**
|
||||
Resets all active messages. For example if composing a new post.
|
||||
|
||||
|
|
|
@ -39,18 +39,6 @@ Discourse.EditCategoryController = Discourse.ObjectController.extend(Discourse.M
|
|||
this.set('controllers.modal.title', this.get('title'));
|
||||
}.observes('title'),
|
||||
|
||||
selectGeneral: function() {
|
||||
this.set('selectedTab', 'general');
|
||||
},
|
||||
|
||||
selectSecurity: function() {
|
||||
this.set('selectedTab', 'security');
|
||||
},
|
||||
|
||||
selectSettings: function() {
|
||||
this.set('selectedTab', 'settings');
|
||||
},
|
||||
|
||||
disabled: function() {
|
||||
if (this.get('saving') || this.get('deleting')) return true;
|
||||
if (!this.get('name')) return true;
|
||||
|
@ -103,83 +91,97 @@ Discourse.EditCategoryController = Discourse.ObjectController.extend(Discourse.M
|
|||
return I18n.t('category.delete');
|
||||
}.property(),
|
||||
|
||||
showCategoryTopic: function() {
|
||||
this.send('closeModal');
|
||||
Discourse.URL.routeTo(this.get('topic_url'));
|
||||
return false;
|
||||
},
|
||||
actions: {
|
||||
|
||||
editPermissions: function(){
|
||||
this.set('editingPermissions', true);
|
||||
},
|
||||
selectGeneral: function() {
|
||||
this.set('selectedTab', 'general');
|
||||
},
|
||||
|
||||
addPermission: function(group, permission_id){
|
||||
this.get('model').addPermission({group_name: group + "", permission: Discourse.PermissionType.create({id: permission_id})});
|
||||
},
|
||||
selectSecurity: function() {
|
||||
this.set('selectedTab', 'security');
|
||||
},
|
||||
|
||||
removePermission: function(permission){
|
||||
this.get('model').removePermission(permission);
|
||||
},
|
||||
selectSettings: function() {
|
||||
this.set('selectedTab', 'settings');
|
||||
},
|
||||
|
||||
saveCategory: function() {
|
||||
var categoryController = this;
|
||||
this.set('saving', true);
|
||||
showCategoryTopic: function() {
|
||||
this.send('closeModal');
|
||||
Discourse.URL.routeTo(this.get('topic_url'));
|
||||
return false;
|
||||
},
|
||||
|
||||
editPermissions: function(){
|
||||
this.set('editingPermissions', true);
|
||||
},
|
||||
|
||||
addPermission: function(group, permission_id){
|
||||
this.get('model').addPermission({group_name: group + "", permission: Discourse.PermissionType.create({id: permission_id})});
|
||||
},
|
||||
|
||||
removePermission: function(permission){
|
||||
this.get('model').removePermission(permission);
|
||||
},
|
||||
|
||||
saveCategory: function() {
|
||||
var categoryController = this;
|
||||
this.set('saving', true);
|
||||
|
||||
|
||||
if( this.get('isUncategorized') ) {
|
||||
$.when(
|
||||
Discourse.SiteSetting.update('uncategorized_color', this.get('color')),
|
||||
Discourse.SiteSetting.update('uncategorized_text_color', this.get('text_color')),
|
||||
Discourse.SiteSetting.update('uncategorized_name', this.get('name'))
|
||||
).then(function(result) {
|
||||
// success
|
||||
categoryController.send('closeModal');
|
||||
// We can't redirect to the uncategorized category on save because the slug
|
||||
// might have changed.
|
||||
Discourse.URL.redirectTo("/categories");
|
||||
}, function(errors) {
|
||||
// errors
|
||||
if(errors.length === 0) errors.push(I18n.t("category.save_error"));
|
||||
categoryController.displayErrors(errors);
|
||||
categoryController.set('saving', false);
|
||||
});
|
||||
} else {
|
||||
this.get('model').save().then(function(result) {
|
||||
// success
|
||||
categoryController.send('closeModal');
|
||||
Discourse.URL.redirectTo("/category/" + Discourse.Category.slugFor(result.category));
|
||||
}, function(errors) {
|
||||
// errors
|
||||
if(errors.length === 0) errors.push(I18n.t("category.creation_error"));
|
||||
categoryController.displayErrors(errors);
|
||||
categoryController.set('saving', false);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
deleteCategory: function() {
|
||||
var categoryController = this;
|
||||
this.set('deleting', true);
|
||||
|
||||
$('#discourse-modal').modal('hide');
|
||||
bootbox.confirm(I18n.t("category.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
if (result) {
|
||||
categoryController.get('model').destroy().then(function(){
|
||||
if( this.get('isUncategorized') ) {
|
||||
$.when(
|
||||
Discourse.SiteSetting.update('uncategorized_color', this.get('color')),
|
||||
Discourse.SiteSetting.update('uncategorized_text_color', this.get('text_color')),
|
||||
Discourse.SiteSetting.update('uncategorized_name', this.get('name'))
|
||||
).then(function(result) {
|
||||
// success
|
||||
categoryController.send('closeModal');
|
||||
// We can't redirect to the uncategorized category on save because the slug
|
||||
// might have changed.
|
||||
Discourse.URL.redirectTo("/categories");
|
||||
}, function(jqXHR){
|
||||
// error
|
||||
$('#discourse-modal').modal('show');
|
||||
categoryController.displayErrors([I18n.t("category.delete_error")]);
|
||||
categoryController.set('deleting', false);
|
||||
}, function(errors) {
|
||||
// errors
|
||||
if(errors.length === 0) errors.push(I18n.t("category.save_error"));
|
||||
categoryController.displayErrors(errors);
|
||||
categoryController.set('saving', false);
|
||||
});
|
||||
} else {
|
||||
$('#discourse-modal').modal('show');
|
||||
categoryController.set('deleting', false);
|
||||
this.get('model').save().then(function(result) {
|
||||
// success
|
||||
categoryController.send('closeModal');
|
||||
Discourse.URL.redirectTo("/category/" + Discourse.Category.slugFor(result.category));
|
||||
}, function(errors) {
|
||||
// errors
|
||||
if(errors.length === 0) errors.push(I18n.t("category.creation_error"));
|
||||
categoryController.displayErrors(errors);
|
||||
categoryController.set('saving', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
deleteCategory: function() {
|
||||
var categoryController = this;
|
||||
this.set('deleting', true);
|
||||
|
||||
$('#discourse-modal').modal('hide');
|
||||
bootbox.confirm(I18n.t("category.delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
if (result) {
|
||||
categoryController.get('model').destroy().then(function(){
|
||||
// success
|
||||
categoryController.send('closeModal');
|
||||
Discourse.URL.redirectTo("/categories");
|
||||
}, function(jqXHR){
|
||||
// error
|
||||
$('#discourse-modal').modal('show');
|
||||
categoryController.displayErrors([I18n.t("category.delete_error")]);
|
||||
categoryController.set('deleting', false);
|
||||
});
|
||||
} else {
|
||||
$('#discourse-modal').modal('show');
|
||||
categoryController.set('deleting', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -20,12 +20,14 @@ Discourse.EditTopicAutoCloseController = Discourse.ObjectController.extend(Disco
|
|||
}
|
||||
}.observes('details.auto_close_at'),
|
||||
|
||||
saveAutoClose: function() {
|
||||
this.setAutoClose( parseFloat(this.get('auto_close_days')) );
|
||||
},
|
||||
actions: {
|
||||
saveAutoClose: function() {
|
||||
this.setAutoClose( parseFloat(this.get('auto_close_days')) );
|
||||
},
|
||||
|
||||
removeAutoClose: function() {
|
||||
this.setAutoClose(null);
|
||||
removeAutoClose: function() {
|
||||
this.setAutoClose(null);
|
||||
}
|
||||
},
|
||||
|
||||
setAutoClose: function(days) {
|
||||
|
|
|
@ -13,10 +13,6 @@ Discourse.FlagController = Discourse.ObjectController.extend(Discourse.ModalFunc
|
|||
this.set('selected', null);
|
||||
},
|
||||
|
||||
changePostActionType: function(action) {
|
||||
this.set('selected', action);
|
||||
},
|
||||
|
||||
submitEnabled: function() {
|
||||
var selected = this.get('selected');
|
||||
if (!selected) return false;
|
||||
|
@ -46,25 +42,31 @@ Discourse.FlagController = Discourse.ObjectController.extend(Discourse.ModalFunc
|
|||
}
|
||||
}.property('selected.is_custom_flag'),
|
||||
|
||||
takeAction: function() {
|
||||
this.createFlag({takeAction: true});
|
||||
this.set('hidden', true);
|
||||
},
|
||||
actions: {
|
||||
takeAction: function() {
|
||||
this.send('createFlag', {takeAction: true});
|
||||
this.set('hidden', true);
|
||||
},
|
||||
|
||||
createFlag: function(opts) {
|
||||
var flagController = this;
|
||||
var postAction = this.get('actionByName.' + this.get('selected.name_key'));
|
||||
var params = this.get('selected.is_custom_flag') ? {message: this.get('message')} : {};
|
||||
createFlag: function(opts) {
|
||||
var flagController = this;
|
||||
var postAction = this.get('actionByName.' + this.get('selected.name_key'));
|
||||
var params = this.get('selected.is_custom_flag') ? {message: this.get('message')} : {};
|
||||
|
||||
if (opts) params = $.extend(params, opts);
|
||||
if (opts) params = $.extend(params, opts);
|
||||
|
||||
$('#discourse-modal').modal('hide');
|
||||
postAction.act(params).then(function() {
|
||||
flagController.send('closeModal');
|
||||
}, function(errors) {
|
||||
$('#discourse-modal').modal('show');
|
||||
flagController.displayErrors(errors);
|
||||
});
|
||||
$('#discourse-modal').modal('hide');
|
||||
postAction.act(params).then(function() {
|
||||
flagController.send('closeModal');
|
||||
}, function(errors) {
|
||||
$('#discourse-modal').modal('show');
|
||||
flagController.displayErrors(errors);
|
||||
});
|
||||
},
|
||||
|
||||
changePostActionType: function(action) {
|
||||
this.set('selected', action);
|
||||
}
|
||||
},
|
||||
|
||||
canDeleteSpammer: function() {
|
||||
|
|
|
@ -10,12 +10,6 @@ Discourse.HeaderController = Discourse.Controller.extend({
|
|||
topic: null,
|
||||
showExtraInfo: null,
|
||||
|
||||
toggleStar: function() {
|
||||
var topic = this.get('topic');
|
||||
if (topic) topic.toggleStar();
|
||||
return false;
|
||||
},
|
||||
|
||||
categories: function() {
|
||||
return Discourse.Category.list();
|
||||
}.property(),
|
||||
|
@ -36,8 +30,16 @@ Discourse.HeaderController = Discourse.Controller.extend({
|
|||
return Discourse.SiteSettings.enable_mobile_theme;
|
||||
}.property(),
|
||||
|
||||
toggleMobileView: function() {
|
||||
Discourse.Mobile.toggleMobileView();
|
||||
actions: {
|
||||
toggleStar: function() {
|
||||
var topic = this.get('topic');
|
||||
if (topic) topic.toggleStar();
|
||||
return false;
|
||||
},
|
||||
|
||||
toggleMobileView: function() {
|
||||
Discourse.Mobile.toggleMobileView();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -25,22 +25,25 @@ Discourse.InviteController = Discourse.ObjectController.extend(Discourse.ModalFu
|
|||
return I18n.t('topic.invite_reply.success', { email: this.get('email') });
|
||||
}.property('email'),
|
||||
|
||||
createInvite: function() {
|
||||
if (this.get('disabled')) return;
|
||||
actions: {
|
||||
createInvite: function() {
|
||||
if (this.get('disabled')) return;
|
||||
|
||||
var inviteController = this;
|
||||
this.set('saving', true);
|
||||
this.set('error', false);
|
||||
this.get('model').inviteUser(this.get('email')).then(function() {
|
||||
// Success
|
||||
inviteController.set('saving', false);
|
||||
return inviteController.set('finished', true);
|
||||
}, function() {
|
||||
// Failure
|
||||
inviteController.set('error', true);
|
||||
return inviteController.set('saving', false);
|
||||
});
|
||||
return false;
|
||||
var inviteController = this;
|
||||
this.set('saving', true);
|
||||
this.set('error', false);
|
||||
this.get('model').inviteUser(this.get('email')).then(function() {
|
||||
// Success
|
||||
inviteController.set('saving', false);
|
||||
return inviteController.set('finished', true);
|
||||
}, function() {
|
||||
// Failure
|
||||
inviteController.set('error', true);
|
||||
return inviteController.set('saving', false);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -113,14 +113,16 @@ Discourse.ListController = Discourse.Controller.extend({
|
|||
}.observes('filterMode', 'category'),
|
||||
|
||||
// Create topic button
|
||||
createTopic: function() {
|
||||
this.get('controllers.composer').open({
|
||||
categoryId: this.get('category.id'),
|
||||
action: Discourse.Composer.CREATE_TOPIC,
|
||||
draft: this.get('draft'),
|
||||
draftKey: this.get('draft_key'),
|
||||
draftSequence: this.get('draft_sequence')
|
||||
});
|
||||
actions: {
|
||||
createTopic: function() {
|
||||
this.get('controllers.composer').open({
|
||||
categoryId: this.get('category.id'),
|
||||
action: Discourse.Composer.CREATE_TOPIC,
|
||||
draft: this.get('draft'),
|
||||
draftKey: this.get('draft_key'),
|
||||
draftSequence: this.get('draft_sequence')
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
canEditCategory: function() {
|
||||
|
|
|
@ -27,32 +27,34 @@ Discourse.ListTopicsController = Discourse.ObjectController.extend({
|
|||
}
|
||||
}.observes('content.draft'),
|
||||
|
||||
// Star a topic
|
||||
toggleStar: function(topic) {
|
||||
topic.toggleStar();
|
||||
},
|
||||
actions: {
|
||||
// Star a topic
|
||||
toggleStar: function(topic) {
|
||||
topic.toggleStar();
|
||||
},
|
||||
|
||||
// clear a pinned topic
|
||||
clearPin: function(topic) {
|
||||
topic.clearPin();
|
||||
},
|
||||
// clear a pinned topic
|
||||
clearPin: function(topic) {
|
||||
topic.clearPin();
|
||||
},
|
||||
|
||||
toggleRankDetails: function() {
|
||||
this.toggleProperty('rankDetailsVisible');
|
||||
},
|
||||
toggleRankDetails: function() {
|
||||
this.toggleProperty('rankDetailsVisible');
|
||||
},
|
||||
|
||||
createTopic: function() {
|
||||
this.get('controllers.list').createTopic();
|
||||
},
|
||||
createTopic: function() {
|
||||
this.get('controllers.list').send('createTopic');
|
||||
},
|
||||
|
||||
// Show newly inserted topics
|
||||
showInserted: function(e) {
|
||||
var tracker = Discourse.TopicTrackingState.current();
|
||||
// Show newly inserted topics
|
||||
showInserted: function(e) {
|
||||
var tracker = Discourse.TopicTrackingState.current();
|
||||
|
||||
// Move inserted into topics
|
||||
this.get('content').loadBefore(tracker.get('newIncoming'));
|
||||
tracker.resetTracking();
|
||||
return false;
|
||||
// Move inserted into topics
|
||||
this.get('content').loadBefore(tracker.get('newIncoming'));
|
||||
tracker.resetTracking();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
allLoaded: function() {
|
||||
|
|
|
@ -46,7 +46,7 @@ Discourse.MergeTopicController = Discourse.ObjectController.extend(Discourse.Sel
|
|||
promise.then(function(result) {
|
||||
// Posts moved
|
||||
mergeTopicController.send('closeModal');
|
||||
mergeTopicController.get('topicController').toggleMultiSelect();
|
||||
mergeTopicController.get('topicController').send('toggleMultiSelect');
|
||||
Em.run.next(function() { Discourse.URL.routeTo(result.url); });
|
||||
}, function() {
|
||||
// Error moving posts
|
||||
|
|
|
@ -37,53 +37,54 @@ Discourse.PreferencesController = Discourse.ObjectController.extend({
|
|||
{ name: I18n.t('user.new_topic_duration.after_n_weeks', { count: 1 }), value: 7 * 60 * 24 },
|
||||
{ name: I18n.t('user.new_topic_duration.last_here'), value: -2 }],
|
||||
|
||||
save: function() {
|
||||
var preferencesController = this;
|
||||
this.set('saving', true);
|
||||
this.set('saved', false);
|
||||
|
||||
// Cook the bio for preview
|
||||
var model = this.get('model');
|
||||
return model.save().then(function() {
|
||||
// model was saved
|
||||
preferencesController.set('saving', false);
|
||||
if (Discourse.User.currentProp('id') === model.get('id')) {
|
||||
Discourse.User.currentProp('name', model.get('name'));
|
||||
}
|
||||
|
||||
preferencesController.set('bio_cooked',
|
||||
Discourse.Markdown.cook(preferencesController.get('bio_raw')));
|
||||
preferencesController.set('saved', true);
|
||||
}, function() {
|
||||
// model failed to save
|
||||
preferencesController.set('saving', false);
|
||||
alert(I18n.t('generic_error'));
|
||||
});
|
||||
},
|
||||
|
||||
saveButtonText: function() {
|
||||
return this.get('saving') ? I18n.t('saving') : I18n.t('save');
|
||||
}.property('saving'),
|
||||
|
||||
changePassword: function() {
|
||||
var preferencesController = this;
|
||||
if (!this.get('passwordProgress')) {
|
||||
this.set('passwordProgress', I18n.t("user.change_password.in_progress"));
|
||||
return this.get('model').changePassword().then(function() {
|
||||
// password changed
|
||||
preferencesController.setProperties({
|
||||
changePasswordProgress: false,
|
||||
passwordProgress: I18n.t("user.change_password.success")
|
||||
});
|
||||
actions: {
|
||||
save: function() {
|
||||
var self = this;
|
||||
this.set('saving', true);
|
||||
this.set('saved', false);
|
||||
|
||||
// Cook the bio for preview
|
||||
var model = this.get('model');
|
||||
return model.save().then(function() {
|
||||
// model was saved
|
||||
self.set('saving', false);
|
||||
if (Discourse.User.currentProp('id') === model.get('id')) {
|
||||
Discourse.User.currentProp('name', model.get('name'));
|
||||
}
|
||||
self.set('bio_cooked', Discourse.Markdown.cook(self.get('bio_raw')));
|
||||
self.set('saved', true);
|
||||
}, function() {
|
||||
// password failed to change
|
||||
preferencesController.setProperties({
|
||||
changePasswordProgress: false,
|
||||
passwordProgress: I18n.t("user.change_password.error")
|
||||
});
|
||||
// model failed to save
|
||||
self.set('saving', false);
|
||||
alert(I18n.t('generic_error'));
|
||||
});
|
||||
},
|
||||
|
||||
changePassword: function() {
|
||||
var self = this;
|
||||
if (!this.get('passwordProgress')) {
|
||||
this.set('passwordProgress', I18n.t("user.change_password.in_progress"));
|
||||
return this.get('model').changePassword().then(function() {
|
||||
// password changed
|
||||
self.setProperties({
|
||||
changePasswordProgress: false,
|
||||
passwordProgress: I18n.t("user.change_password.success")
|
||||
});
|
||||
}, function() {
|
||||
// password failed to change
|
||||
self.setProperties({
|
||||
changePasswordProgress: false,
|
||||
passwordProgress: I18n.t("user.change_password.error")
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -22,17 +22,16 @@ Discourse.PreferencesEmailController = Discourse.ObjectController.extend({
|
|||
return I18n.t("user.change");
|
||||
}.property('saving'),
|
||||
|
||||
changeEmail: function() {
|
||||
var preferencesEmailController = this;
|
||||
this.set('saving', true);
|
||||
return this.get('content').changeEmail(this.get('newEmail')).then(function() {
|
||||
preferencesEmailController.set('success', true);
|
||||
}, function() {
|
||||
preferencesEmailController.setProperties({
|
||||
error: true,
|
||||
saving: false
|
||||
actions: {
|
||||
changeEmail: function() {
|
||||
var self = this;
|
||||
this.set('saving', true);
|
||||
return this.get('content').changeEmail(this.get('newEmail')).then(function() {
|
||||
self.set('success', true);
|
||||
}, function() {
|
||||
self.setProperties({ error: true, saving: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -41,21 +41,24 @@ Discourse.PreferencesUsernameController = Discourse.ObjectController.extend({
|
|||
return I18n.t("user.change");
|
||||
}.property('saving'),
|
||||
|
||||
changeUsername: function() {
|
||||
var preferencesUsernameController = this;
|
||||
return bootbox.confirm(I18n.t("user.change_username.confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
if (result) {
|
||||
preferencesUsernameController.set('saving', true);
|
||||
preferencesUsernameController.get('content').changeUsername(preferencesUsernameController.get('newUsername')).then(function() {
|
||||
Discourse.URL.redirectTo("/users/" + preferencesUsernameController.get('newUsername').toLowerCase() + "/preferences");
|
||||
}, function() {
|
||||
// error
|
||||
preferencesUsernameController.set('error', true);
|
||||
preferencesUsernameController.set('saving', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
actions: {
|
||||
changeUsername: function() {
|
||||
var preferencesUsernameController = this;
|
||||
return bootbox.confirm(I18n.t("user.change_username.confirm"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
if (result) {
|
||||
preferencesUsernameController.set('saving', true);
|
||||
preferencesUsernameController.get('content').changeUsername(preferencesUsernameController.get('newUsername')).then(function() {
|
||||
Discourse.URL.redirectTo("/users/" + preferencesUsernameController.get('newUsername').toLowerCase() + "/preferences");
|
||||
}, function() {
|
||||
// error
|
||||
preferencesUsernameController.set('error', true);
|
||||
preferencesUsernameController.set('saving', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -62,14 +62,20 @@ Discourse.SearchController = Em.ArrayController.extend(Discourse.Presence, {
|
|||
}.property('typeFilter', 'loading'),
|
||||
|
||||
termChanged: function() {
|
||||
this.cancelType();
|
||||
this.cancelTypeFilter();
|
||||
}.observes('term'),
|
||||
|
||||
moreOfType: function(type) {
|
||||
this.set('typeFilter', type);
|
||||
actions: {
|
||||
moreOfType: function(type) {
|
||||
this.set('typeFilter', type);
|
||||
},
|
||||
|
||||
cancelType: function() {
|
||||
this.cancelTypeFilter();
|
||||
}
|
||||
},
|
||||
|
||||
cancelType: function() {
|
||||
cancelTypeFilter: function() {
|
||||
this.set('typeFilter', null);
|
||||
},
|
||||
|
||||
|
|
|
@ -11,10 +11,12 @@ Discourse.ShareController = Discourse.Controller.extend({
|
|||
needs: ['topic'],
|
||||
|
||||
// Close the share controller
|
||||
close: function() {
|
||||
this.set('link', '');
|
||||
this.set('postNumber', '');
|
||||
return false;
|
||||
actions: {
|
||||
close: function() {
|
||||
this.set('link', '');
|
||||
this.set('postNumber', '');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
shareLinks: function() {
|
||||
|
|
|
@ -42,7 +42,7 @@ Discourse.SplitTopicController = Discourse.ObjectController.extend(Discourse.Sel
|
|||
}).then(function(result) {
|
||||
// Posts moved
|
||||
self.send('closeModal');
|
||||
self.get('topicController').toggleMultiSelect();
|
||||
self.get('topicController').send('toggleMultiSelect');
|
||||
Em.run.next(function() { Discourse.URL.routeTo(result.url); });
|
||||
}, function() {
|
||||
// Error moving posts
|
||||
|
|
|
@ -10,12 +10,14 @@ Discourse.TopicAdminMenuController = Discourse.ObjectController.extend({
|
|||
menuVisible: false,
|
||||
needs: ['modal'],
|
||||
|
||||
show: function() {
|
||||
this.set('menuVisible', true);
|
||||
},
|
||||
actions: {
|
||||
show: function() {
|
||||
this.set('menuVisible', true);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.set('menuVisible', false);
|
||||
hide: function() {
|
||||
this.set('menuVisible', false);
|
||||
}
|
||||
},
|
||||
|
||||
showRecover: Em.computed.and('deleted', 'details.can_recover')
|
||||
|
|
|
@ -21,6 +21,209 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||
this.set('selectedReplies', new Em.Set());
|
||||
},
|
||||
|
||||
actions: {
|
||||
jumpTop: function() {
|
||||
Discourse.URL.routeTo(this.get('url'));
|
||||
},
|
||||
|
||||
jumpBottom: function() {
|
||||
Discourse.URL.routeTo(this.get('lastPostUrl'));
|
||||
},
|
||||
|
||||
toggleSummary: function() {
|
||||
this.toggleProperty('summaryCollapsed');
|
||||
},
|
||||
|
||||
selectAll: function() {
|
||||
var posts = this.get('postStream.posts');
|
||||
var selectedPosts = this.get('selectedPosts');
|
||||
if (posts) {
|
||||
selectedPosts.addObjects(posts);
|
||||
}
|
||||
this.set('allPostsSelected', true);
|
||||
},
|
||||
|
||||
deselectAll: function() {
|
||||
this.get('selectedPosts').clear();
|
||||
this.get('selectedReplies').clear();
|
||||
this.set('allPostsSelected', false);
|
||||
},
|
||||
|
||||
/**
|
||||
Toggle a participant for filtering
|
||||
|
||||
@method toggleParticipant
|
||||
**/
|
||||
toggleParticipant: function(user) {
|
||||
this.get('postStream').toggleParticipant(Em.get(user, 'username'));
|
||||
},
|
||||
|
||||
editTopic: function() {
|
||||
if (!this.get('details.can_edit')) return false;
|
||||
|
||||
this.setProperties({
|
||||
editingTopic: true,
|
||||
newTitle: this.get('title'),
|
||||
newCategoryId: this.get('category_id')
|
||||
});
|
||||
return false;
|
||||
},
|
||||
|
||||
// close editing mode
|
||||
cancelEditingTopic: function() {
|
||||
this.set('editingTopic', false);
|
||||
},
|
||||
|
||||
toggleMultiSelect: function() {
|
||||
this.toggleProperty('multiSelect');
|
||||
},
|
||||
|
||||
finishedEditingTopic: function() {
|
||||
var topicController = this;
|
||||
if (this.get('editingTopic')) {
|
||||
|
||||
var topic = this.get('model');
|
||||
|
||||
// Topic title hasn't been sanitized yet, so the template shouldn't trust it.
|
||||
this.set('topicSaving', true);
|
||||
|
||||
// manually update the titles & category
|
||||
topic.setProperties({
|
||||
title: this.get('newTitle'),
|
||||
category_id: parseInt(this.get('newCategoryId'), 10),
|
||||
fancy_title: this.get('newTitle')
|
||||
});
|
||||
|
||||
// save the modifications
|
||||
topic.save().then(function(result){
|
||||
// update the title if it has been changed (cleaned up) server-side
|
||||
var title = result.basic_topic.title;
|
||||
var fancy_title = result.basic_topic.fancy_title;
|
||||
topic.setProperties({
|
||||
title: title,
|
||||
fancy_title: fancy_title
|
||||
});
|
||||
topicController.set('topicSaving', false);
|
||||
}, function(error) {
|
||||
topicController.set('editingTopic', true);
|
||||
topicController.set('topicSaving', false);
|
||||
if (error && error.responseText) {
|
||||
bootbox.alert($.parseJSON(error.responseText).errors[0]);
|
||||
} else {
|
||||
bootbox.alert(I18n.t('generic_error'));
|
||||
}
|
||||
});
|
||||
|
||||
// close editing mode
|
||||
topicController.set('editingTopic', false);
|
||||
}
|
||||
},
|
||||
|
||||
toggledSelectedPost: function(post) {
|
||||
this.performTogglePost(post);
|
||||
},
|
||||
|
||||
toggledSelectedPostReplies: function(post) {
|
||||
var selectedReplies = this.get('selectedReplies');
|
||||
if (this.performTogglePost(post)) {
|
||||
selectedReplies.addObject(post);
|
||||
} else {
|
||||
selectedReplies.removeObject(post);
|
||||
}
|
||||
},
|
||||
|
||||
deleteSelected: function() {
|
||||
var self = this;
|
||||
bootbox.confirm(I18n.t("post.delete.confirm", { count: this.get('selectedPostsCount')}), function(result) {
|
||||
if (result) {
|
||||
|
||||
// If all posts are selected, it's the same thing as deleting the topic
|
||||
if (self.get('allPostsSelected')) {
|
||||
return self.deleteTopic();
|
||||
}
|
||||
|
||||
var selectedPosts = self.get('selectedPosts'),
|
||||
selectedReplies = self.get('selectedReplies'),
|
||||
postStream = self.get('postStream'),
|
||||
toRemove = new Ember.Set();
|
||||
|
||||
|
||||
Discourse.Post.deleteMany(selectedPosts, selectedReplies);
|
||||
postStream.get('posts').forEach(function (p) {
|
||||
if (self.postSelected(p)) { toRemove.addObject(p); }
|
||||
});
|
||||
|
||||
postStream.removePosts(toRemove);
|
||||
self.send('toggleMultiSelect');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
toggleVisibility: function() {
|
||||
this.get('content').toggleStatus('visible');
|
||||
},
|
||||
|
||||
toggleClosed: function() {
|
||||
this.get('content').toggleStatus('closed');
|
||||
},
|
||||
|
||||
togglePinned: function() {
|
||||
this.get('content').toggleStatus('pinned');
|
||||
},
|
||||
|
||||
toggleArchived: function() {
|
||||
this.get('content').toggleStatus('archived');
|
||||
},
|
||||
|
||||
convertToRegular: function() {
|
||||
this.get('content').convertArchetype('regular');
|
||||
},
|
||||
|
||||
// Toggle the star on the topic
|
||||
toggleStar: function() {
|
||||
this.get('content').toggleStar();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
Clears the pin from a topic for the currently logged in user
|
||||
|
||||
@method clearPin
|
||||
**/
|
||||
clearPin: function() {
|
||||
this.get('content').clearPin();
|
||||
},
|
||||
|
||||
resetRead: function() {
|
||||
Discourse.ScreenTrack.current().reset();
|
||||
this.unsubscribe();
|
||||
|
||||
var topicController = this;
|
||||
this.get('model').resetRead().then(function() {
|
||||
topicController.set('message', I18n.t("topic.read_position_reset"));
|
||||
topicController.set('postStream.loaded', false);
|
||||
});
|
||||
},
|
||||
|
||||
replyAsNewTopic: function(post) {
|
||||
var composerController = this.get('controllers.composer');
|
||||
var promise = composerController.open({
|
||||
action: Discourse.Composer.CREATE_TOPIC,
|
||||
draftKey: Discourse.Composer.REPLY_AS_NEW_TOPIC_KEY
|
||||
});
|
||||
var postUrl = "" + location.protocol + "//" + location.host + (post.get('url'));
|
||||
var postLink = "[" + (this.get('title')) + "](" + postUrl + ")";
|
||||
|
||||
promise.then(function() {
|
||||
Discourse.Post.loadQuote(post.get('id')).then(function(q) {
|
||||
composerController.appendText(I18n.t("post.continue_discussion", {
|
||||
postLink: postLink
|
||||
}) + "\n\n" + q);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
jumpTopDisabled: function() {
|
||||
return (this.get('progressPosition') === 1);
|
||||
}.property('postStream.filteredPostsCount', 'progressPosition'),
|
||||
|
@ -78,7 +281,7 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||
multiSelectChanged: function() {
|
||||
// Deselect all posts when multi select is turned off
|
||||
if (!this.get('multiSelect')) {
|
||||
this.deselectAll();
|
||||
this.send('deselectAll');
|
||||
}
|
||||
}.observes('multiSelect'),
|
||||
|
||||
|
@ -109,156 +312,6 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||
return false;
|
||||
},
|
||||
|
||||
toggledSelectedPost: function(post) {
|
||||
var selectedPosts = this.get('selectedPosts');
|
||||
if (this.postSelected(post)) {
|
||||
this.deselectPost(post);
|
||||
return false;
|
||||
} else {
|
||||
selectedPosts.addObject(post);
|
||||
|
||||
// If the user manually selects all posts, all posts are selected
|
||||
if (selectedPosts.length === this.get('posts_count')) {
|
||||
this.set('allPostsSelected', true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
toggledSelectedPostReplies: function(post) {
|
||||
var selectedReplies = this.get('selectedReplies');
|
||||
if (this.toggledSelectedPost(post)) {
|
||||
selectedReplies.addObject(post);
|
||||
} else {
|
||||
selectedReplies.removeObject(post);
|
||||
}
|
||||
},
|
||||
|
||||
selectAll: function() {
|
||||
var posts = this.get('postStream.posts');
|
||||
var selectedPosts = this.get('selectedPosts');
|
||||
if (posts) {
|
||||
selectedPosts.addObjects(posts);
|
||||
}
|
||||
this.set('allPostsSelected', true);
|
||||
},
|
||||
|
||||
deselectAll: function() {
|
||||
this.get('selectedPosts').clear();
|
||||
this.get('selectedReplies').clear();
|
||||
this.set('allPostsSelected', false);
|
||||
},
|
||||
|
||||
toggleMultiSelect: function() {
|
||||
this.toggleProperty('multiSelect');
|
||||
},
|
||||
|
||||
toggleSummary: function() {
|
||||
this.toggleProperty('summaryCollapsed');
|
||||
},
|
||||
|
||||
editTopic: function() {
|
||||
if (!this.get('details.can_edit')) return false;
|
||||
|
||||
this.setProperties({
|
||||
editingTopic: true,
|
||||
newTitle: this.get('title'),
|
||||
newCategoryId: this.get('category_id')
|
||||
});
|
||||
return false;
|
||||
},
|
||||
|
||||
// close editing mode
|
||||
cancelEditingTopic: function() {
|
||||
this.set('editingTopic', false);
|
||||
},
|
||||
|
||||
finishedEditingTopic: function() {
|
||||
var topicController = this;
|
||||
if (this.get('editingTopic')) {
|
||||
|
||||
var topic = this.get('model');
|
||||
|
||||
// Topic title hasn't been sanitized yet, so the template shouldn't trust it.
|
||||
this.set('topicSaving', true);
|
||||
|
||||
// manually update the titles & category
|
||||
topic.setProperties({
|
||||
title: this.get('newTitle'),
|
||||
category_id: parseInt(this.get('newCategoryId'), 10),
|
||||
fancy_title: this.get('newTitle')
|
||||
});
|
||||
|
||||
// save the modifications
|
||||
topic.save().then(function(result){
|
||||
// update the title if it has been changed (cleaned up) server-side
|
||||
var title = result.basic_topic.title;
|
||||
var fancy_title = result.basic_topic.fancy_title;
|
||||
topic.setProperties({
|
||||
title: title,
|
||||
fancy_title: fancy_title
|
||||
});
|
||||
topicController.set('topicSaving', false);
|
||||
}, function(error) {
|
||||
topicController.set('editingTopic', true);
|
||||
topicController.set('topicSaving', false);
|
||||
if (error && error.responseText) {
|
||||
bootbox.alert($.parseJSON(error.responseText).errors[0]);
|
||||
} else {
|
||||
bootbox.alert(I18n.t('generic_error'));
|
||||
}
|
||||
});
|
||||
|
||||
// close editing mode
|
||||
topicController.set('editingTopic', false);
|
||||
}
|
||||
},
|
||||
|
||||
deleteSelected: function() {
|
||||
var self = this;
|
||||
bootbox.confirm(I18n.t("post.delete.confirm", { count: this.get('selectedPostsCount')}), function(result) {
|
||||
if (result) {
|
||||
|
||||
// If all posts are selected, it's the same thing as deleting the topic
|
||||
if (self.get('allPostsSelected')) {
|
||||
return self.deleteTopic();
|
||||
}
|
||||
|
||||
var selectedPosts = self.get('selectedPosts'),
|
||||
selectedReplies = self.get('selectedReplies'),
|
||||
postStream = self.get('postStream'),
|
||||
toRemove = new Ember.Set();
|
||||
|
||||
|
||||
Discourse.Post.deleteMany(selectedPosts, selectedReplies);
|
||||
postStream.get('posts').forEach(function (p) {
|
||||
if (self.postSelected(p)) { toRemove.addObject(p); }
|
||||
});
|
||||
|
||||
postStream.removePosts(toRemove);
|
||||
self.toggleMultiSelect();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
jumpTop: function() {
|
||||
Discourse.URL.routeTo(this.get('url'));
|
||||
},
|
||||
|
||||
jumpBottom: function() {
|
||||
Discourse.URL.routeTo(this.get('lastPostUrl'));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
Toggle a participant for filtering
|
||||
|
||||
@method toggleParticipant
|
||||
**/
|
||||
toggleParticipant: function(user) {
|
||||
this.get('postStream').toggleParticipant(Em.get(user, 'username'));
|
||||
},
|
||||
|
||||
showFavoriteButton: function() {
|
||||
return Discourse.User.current() && !this.get('isPrivateMessage');
|
||||
}.property('isPrivateMessage'),
|
||||
|
@ -272,52 +325,6 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||
this.get('content').destroy(Discourse.User.current());
|
||||
},
|
||||
|
||||
resetRead: function() {
|
||||
Discourse.ScreenTrack.current().reset();
|
||||
this.unsubscribe();
|
||||
|
||||
var topicController = this;
|
||||
this.get('model').resetRead().then(function() {
|
||||
topicController.set('message', I18n.t("topic.read_position_reset"));
|
||||
topicController.set('postStream.loaded', false);
|
||||
});
|
||||
},
|
||||
|
||||
toggleVisibility: function() {
|
||||
this.get('content').toggleStatus('visible');
|
||||
},
|
||||
|
||||
toggleClosed: function() {
|
||||
this.get('content').toggleStatus('closed');
|
||||
},
|
||||
|
||||
togglePinned: function() {
|
||||
this.get('content').toggleStatus('pinned');
|
||||
},
|
||||
|
||||
toggleArchived: function() {
|
||||
this.get('content').toggleStatus('archived');
|
||||
},
|
||||
|
||||
convertToRegular: function() {
|
||||
this.get('content').convertArchetype('regular');
|
||||
},
|
||||
|
||||
// Toggle the star on the topic
|
||||
toggleStar: function() {
|
||||
this.get('content').toggleStar();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
Clears the pin from a topic for the currently logged in user
|
||||
|
||||
@method clearPin
|
||||
**/
|
||||
clearPin: function() {
|
||||
this.get('content').clearPin();
|
||||
},
|
||||
|
||||
// Receive notifications for this topic
|
||||
subscribe: function() {
|
||||
|
||||
|
@ -383,24 +390,6 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||
return false;
|
||||
},
|
||||
|
||||
replyAsNewTopic: function(post) {
|
||||
var composerController = this.get('controllers.composer');
|
||||
var promise = composerController.open({
|
||||
action: Discourse.Composer.CREATE_TOPIC,
|
||||
draftKey: Discourse.Composer.REPLY_AS_NEW_TOPIC_KEY
|
||||
});
|
||||
var postUrl = "" + location.protocol + "//" + location.host + (post.get('url'));
|
||||
var postLink = "[" + (this.get('title')) + "](" + postUrl + ")";
|
||||
|
||||
promise.then(function() {
|
||||
Discourse.Post.loadQuote(post.get('id')).then(function(q) {
|
||||
composerController.appendText(I18n.t("post.continue_discussion", {
|
||||
postLink: postLink
|
||||
}) + "\n\n" + q);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Topic related
|
||||
reply: function() {
|
||||
this.replyToPost();
|
||||
|
@ -470,6 +459,22 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
|||
}
|
||||
},
|
||||
|
||||
performTogglePost: function(post) {
|
||||
var selectedPosts = this.get('selectedPosts');
|
||||
if (this.postSelected(post)) {
|
||||
this.deselectPost(post);
|
||||
return false;
|
||||
} else {
|
||||
selectedPosts.addObject(post);
|
||||
|
||||
// If the user manually selects all posts, all posts are selected
|
||||
if (selectedPosts.length === this.get('posts_count')) {
|
||||
this.set('allPostsSelected', true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
removeAllowedUser: function(username) {
|
||||
this.get('details').removeAllowedUser(username);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ Discourse.UploadSelectorController = Discourse.Controller.extend(Discourse.Modal
|
|||
localSelected: true,
|
||||
remoteSelected: Em.computed.not('localSelected'),
|
||||
|
||||
selectLocal: function() { this.set('localSelected', true); },
|
||||
selectRemote: function() { this.set('localSelected', false); },
|
||||
actions: {
|
||||
selectLocal: function() { this.set('localSelected', true); },
|
||||
selectRemote: function() { this.set('localSelected', false); }
|
||||
},
|
||||
|
||||
localTitle: function() { return Discourse.UploadSelectorController.translate("local_title"); }.property(),
|
||||
remoteTitle: function() { return Discourse.UploadSelectorController.translate("remote_title"); }.property(),
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
@module Discourse
|
||||
**/
|
||||
Discourse.UserInvitedController = Discourse.ObjectController.extend({
|
||||
rescind: function(invite) {
|
||||
invite.rescind();
|
||||
return false;
|
||||
|
||||
actions: {
|
||||
rescind: function(invite) {
|
||||
invite.rescind();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
**/
|
||||
Discourse.ApplicationRoute = Em.Route.extend({
|
||||
|
||||
events: {
|
||||
actions: {
|
||||
showLogin: function() {
|
||||
Discourse.Route.showModal(this, 'login');
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ Discourse.ListCategoriesRoute = Discourse.Route.extend({
|
|||
|
||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||
|
||||
events: {
|
||||
actions: {
|
||||
createCategory: function() {
|
||||
Discourse.Route.showModal(this, 'editCategory', Discourse.Category.create({
|
||||
color: 'AB9364', text_color: 'FFFFFF', hotness: 5, group_permissions: [{group_name: "everyone", permission_type: 1}],
|
||||
|
|
|
@ -15,7 +15,7 @@ Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
|||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
events: {
|
||||
actions: {
|
||||
showAvatarSelector: function() {
|
||||
Discourse.Route.showModal(this, 'avatarSelector');
|
||||
// all the properties needed for displaying the avatar selector modal
|
||||
|
|
|
@ -10,7 +10,7 @@ Discourse.TopicRoute = Discourse.Route.extend({
|
|||
|
||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||
|
||||
events: {
|
||||
actions: {
|
||||
// Modals that can pop up within a topic
|
||||
|
||||
showFlags: function(post) {
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
</li>
|
||||
<li class='current-user'>
|
||||
{{#if currentUser}}
|
||||
{{#linkTo 'userActivity.index' currentUser titleKey="current_user" class="icon"}}{{boundAvatar currentUser imageSize="medium" }}{{/linkTo}}
|
||||
{{#link-to 'userActivity.index' currentUser titleKey="current_user" class="icon"}}{{boundAvatar currentUser imageSize="medium" }}{{/link-to}}
|
||||
{{else}}
|
||||
<div class="icon not-logged-in-avatar" {{action showLogin}}><i class='icon-user'></i></div>
|
||||
{{/if}}
|
||||
|
@ -139,7 +139,7 @@
|
|||
{{#if categories}}
|
||||
<ul class="category-links">
|
||||
<li class='heading' title="{{i18n filters.categories.help}}">
|
||||
{{#linkTo "list.categories"}}{{i18n filters.categories.title}}{{/linkTo}}
|
||||
{{#link-to "list.categories"}}{{i18n filters.categories.title}}{{/link-to}}
|
||||
</li>
|
||||
|
||||
{{#each categories}}
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<a href='#' {{action createTopic}}>{{i18n topic.suggest_create_topic}}</a>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#linkTo 'list.categories'}}{{i18n topic.browse_all_categories}}{{/linkTo}} {{i18n or}} {{#linkTo 'list.latest'}}{{i18n topic.view_latest_topics}}{{/linkTo}}
|
||||
{{#link-to 'list.categories'}}{{i18n topic.browse_all_categories}}{{/link-to}} {{i18n or}} {{#link-to 'list.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<a href='#' {{action createTopic}}>{{i18n topic.suggest_create_topic}}</a>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#linkTo 'list.categories'}}{{i18n topic.browse_all_categories}}{{/linkTo}} {{i18n or}} {{#linkTo 'list.latest'}}{{i18n topic.view_latest_topics}}{{/linkTo}}
|
||||
{{#link-to 'list.categories'}}{{i18n topic.browse_all_categories}}{{/link-to}} {{i18n or}} {{#link-to 'list.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id='user-info'>
|
||||
<nav class='buttons'>
|
||||
{{#if can_edit}}
|
||||
{{#linkTo "preferences" class="btn"}}{{i18n user.edit}}{{/linkTo}}
|
||||
{{#link-to "preferences" class="btn"}}{{i18n user.edit}}{{/link-to}}
|
||||
{{/if}}
|
||||
<br/>
|
||||
{{#if can_send_private_message_to_user}}
|
||||
|
@ -16,13 +16,13 @@
|
|||
<ul class='action-list nav-stacked side-nav'>
|
||||
{{#if privateMessageView}}
|
||||
<li {{bindAttr class=":noGlyph privateMessagesActive:active"}}>
|
||||
{{#linkTo 'userPrivateMessages.index' model}}{{i18n user.messages.all}}{{/linkTo}}
|
||||
{{#link-to 'userPrivateMessages.index' model}}{{i18n user.messages.all}}{{/link-to}}
|
||||
</li>
|
||||
<li {{bindAttr class=":noGlyph privateMessagesMineActive:active"}}>
|
||||
{{#linkTo 'userPrivateMessages.mine' model}}{{i18n user.messages.mine}}{{/linkTo}}
|
||||
{{#link-to 'userPrivateMessages.mine' model}}{{i18n user.messages.mine}}{{/link-to}}
|
||||
</li>
|
||||
<li {{bindAttr class=":noGlyph privateMessagesUnreadActive:active"}}>
|
||||
{{#linkTo 'userPrivateMessages.unread' model}}{{i18n user.messages.unread}}{{/linkTo}}
|
||||
{{#link-to 'userPrivateMessages.unread' model}}{{i18n user.messages.unread}}{{/link-to}}
|
||||
</li>
|
||||
|
||||
{{else}}
|
||||
|
@ -48,7 +48,7 @@
|
|||
<dt>{{i18n user.last_seen}}:</dt><dd>{{date last_seen_at}}</dd>
|
||||
{{/if}}
|
||||
{{#if invited_by}}
|
||||
<dt>{{i18n user.invited_by}}:</dt><dd>{{#linkTo 'userActivity' invited_by}}{{invited_by.username}}{{/linkTo}}</dd>
|
||||
<dt>{{i18n user.invited_by}}:</dt><dd>{{#link-to 'userActivity' invited_by}}{{invited_by.username}}{{/link-to}}</dd>
|
||||
{{/if}}
|
||||
{{#if email}}
|
||||
<dt>{{i18n user.email.title}}:</dt><dd {{bindAttr title="email"}}>{{email}}</dd>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="controls">
|
||||
<span class='static'>{{username}}</span>
|
||||
{{#if can_edit_username}}
|
||||
{{#linkTo "preferences.username" class="btn pad-left"}}<i class="icon-pencil"></i>{{/linkTo}}
|
||||
{{#link-to "preferences.username" class="btn pad-left"}}<i class="icon-pencil"></i>{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='instructions'>
|
||||
|
@ -28,7 +28,7 @@
|
|||
<div class="controls">
|
||||
<span class='static'>{{email}}</span>
|
||||
{{#if can_edit_email}}
|
||||
{{#linkTo "preferences.email" class="btn pad-left"}}<i class="icon-pencil"></i>{{/linkTo}}
|
||||
{{#link-to "preferences.email" class="btn pad-left"}}<i class="icon-pencil"></i>{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='instructions'>
|
||||
|
|
|
@ -12,19 +12,19 @@
|
|||
{{/if}}
|
||||
<ul class="nav nav-pills">
|
||||
<li>
|
||||
{{#linkTo 'userActivity'}}{{i18n user.activity_stream}}{{/linkTo}}
|
||||
{{#link-to 'userActivity'}}{{i18n user.activity_stream}}{{/link-to}}
|
||||
</li>
|
||||
{{#if canSeePrivateMessages}}
|
||||
<li>
|
||||
{{#linkTo 'userPrivateMessages'}}{{i18n user.private_messages}}{{/linkTo}}
|
||||
{{#link-to 'userPrivateMessages'}}{{i18n user.private_messages}}{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
<li>
|
||||
{{#linkTo 'user.invited'}}{{i18n user.invited.title}}{{/linkTo}}
|
||||
{{#link-to 'user.invited'}}{{i18n user.invited.title}}{{/link-to}}
|
||||
</li>
|
||||
{{#if can_edit}}
|
||||
<li>
|
||||
{{#linkTo 'preferences'}}{{i18n user.preferences}}{{/linkTo}}
|
||||
{{#link-to 'preferences'}}{{i18n user.preferences}}{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
|
|
@ -14,7 +14,7 @@ Discourse.FavoriteButton = Discourse.ButtonView.extend({
|
|||
shouldRerender: Discourse.View.renderIfChanged('controller.starred'),
|
||||
|
||||
click: function() {
|
||||
this.get('controller').toggleStar();
|
||||
this.get('controller').send('toggleStar');
|
||||
},
|
||||
|
||||
renderIcon: function(buffer) {
|
||||
|
|
|
@ -45,7 +45,7 @@ Discourse.ShareView = Discourse.View.extend({
|
|||
// link is clicked (which is a click event) while the share dialog is showing.
|
||||
if (shareView.$().has(e.target).length !== 0) { return; }
|
||||
|
||||
shareView.get('controller').close();
|
||||
shareView.get('controller').send('close');
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ Discourse.ShareView = Discourse.View.extend({
|
|||
|
||||
$('html').on('keydown.share-view', function(e){
|
||||
if (e.keyCode === 27) {
|
||||
shareView.get('controller').close();
|
||||
shareView.get('controller').send('close');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -13,11 +13,11 @@ Discourse.TopicAdminMenuView = Discourse.View.extend({
|
|||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
var topicAdminMenuView = this;
|
||||
var self = this;
|
||||
$('html').on('mouseup.discourse-topic-admin-menu', function(e) {
|
||||
var $target = $(e.target);
|
||||
if ($target.is('button') || topicAdminMenuView.$().has($target).length === 0) {
|
||||
topicAdminMenuView.get('controller').hide();
|
||||
if ($target.is('button') || self.$().has($target).length === 0) {
|
||||
self.get('controller').send('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"description": "This is the EmberJS client to access a Discourse Server",
|
||||
"url": "http://www.discourse.org/",
|
||||
"options": {
|
||||
"exclude": "external,external_production,defer",
|
||||
"exclude": "development,production,defer",
|
||||
"outdir": "./build"
|
||||
}
|
||||
}
|
|
@ -1,7 +1,37 @@
|
|||
//= require_tree ./discourse/ember
|
||||
|
||||
// The rest of the externals
|
||||
//= require_tree ./external
|
||||
// The Vendored JS
|
||||
//= require LAB.js
|
||||
//= require Markdown.Converter.js
|
||||
//= require Markdown.Editor.js
|
||||
//= require Markdown.Sanitizer.js
|
||||
//= require better_markdown.js
|
||||
//= require bootbox.js
|
||||
//= require bootstrap-alert.js
|
||||
//= require bootstrap-button.js
|
||||
//= require bootstrap-dropdown.js
|
||||
//= require bootstrap-modal.js
|
||||
//= require bootstrap-transition.js
|
||||
//= require browser-update.js
|
||||
//= require chosen.jquery.js
|
||||
//= require ember-renderspeed.js
|
||||
//= require favcount.js
|
||||
//= require handlebars.js
|
||||
//= require jquery.ba-replacetext.js
|
||||
//= require jquery.ba-resize.min.js
|
||||
//= require jquery.color.js
|
||||
//= require jquery.cookie.js
|
||||
//= require jquery.fileupload.js
|
||||
//= require jquery.iframe-transport.js
|
||||
//= require jquery.putcursoratend.js
|
||||
//= require jquery.tagsinput.js
|
||||
//= require jquery.ui.widget.js
|
||||
//= require lodash.js
|
||||
//= require md5.js
|
||||
//= require modernizr.custom.95264.js
|
||||
//= require mousetrap.js
|
||||
//= require rsvp.js
|
||||
//= require show-html.js
|
||||
|
||||
//= require ./discourse/helpers/i18n_helpers
|
||||
//= require ./discourse/mixins/ajax
|
||||
|
@ -39,4 +69,4 @@
|
|||
//= require_tree ./discourse/templates
|
||||
//= require_tree ./discourse/routes
|
||||
|
||||
//= require ./external/browser-update.js
|
||||
//= require browser-update.js
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
//= require_tree ./admin
|
|
@ -7,7 +7,7 @@ window.PagedownCustom = {
|
|||
description: I18n.t("composer.quote_post_title"),
|
||||
execute: function() {
|
||||
// AWFUL but I can't figure out how to call a controller method from outside our app
|
||||
return Discourse.__container__.lookup('controller:composer').importQuote();
|
||||
return Discourse.__container__.lookup('controller:composer').send('importQuote');
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -29,6 +29,7 @@ class TopicsController < ApplicationController
|
|||
return wordpress if params[:best].present?
|
||||
|
||||
opts = params.slice(:username_filters, :filter, :page, :post_number)
|
||||
|
||||
begin
|
||||
@topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts)
|
||||
rescue Discourse::NotFound
|
||||
|
|
|
@ -113,8 +113,8 @@ module Discourse
|
|||
|
||||
# ember stuff only used for asset precompliation, production variant plays up
|
||||
config.ember.variant = :development
|
||||
config.ember.ember_location = "#{Rails.root}/app/assets/javascripts/external_production/ember.js"
|
||||
config.ember.handlebars_location = "#{Rails.root}/app/assets/javascripts/external/handlebars.js"
|
||||
config.ember.ember_location = "#{Rails.root}/vendor/assets/javascripts/production/ember.js"
|
||||
config.ember.handlebars_location = "#{Rails.root}/vendor/assets/javascripts/handlebars.js"
|
||||
|
||||
# Since we are using strong_parameters, we can disable and remove
|
||||
# attr_accessible.
|
||||
|
|
|
@ -13,9 +13,6 @@ paths:
|
|||
- test/javascripts/**/*.js
|
||||
|
||||
exclude_paths:
|
||||
- app/assets/javascripts/external/*
|
||||
- app/assets/javascripts/external_production/*
|
||||
- app/assets/javascripts/external_development/*
|
||||
- app/assets/javascripts/defer/*
|
||||
- app/assets/javascripts/locales/i18n.js
|
||||
|
||||
|
|
|
@ -93,11 +93,11 @@ module PrettyText
|
|||
ctx["helpers"] = Helpers.new
|
||||
|
||||
ctx_load(ctx,
|
||||
"app/assets/javascripts/external/md5.js",
|
||||
"app/assets/javascripts/external/lodash.js",
|
||||
"app/assets/javascripts/external/Markdown.Converter.js",
|
||||
"vendor/assets/javascripts/md5.js",
|
||||
"vendor/assets/javascripts/lodash.js",
|
||||
"vendor/assets/javascripts/Markdown.Converter.js",
|
||||
"lib/headless-ember.js",
|
||||
"app/assets/javascripts/external/rsvp.js",
|
||||
"vendor/assets/javascripts/rsvp.js",
|
||||
Rails.configuration.ember.handlebars_location)
|
||||
|
||||
ctx.eval("var Discourse = {}; Discourse.SiteSettings = #{SiteSetting.client_settings_json};")
|
||||
|
@ -107,7 +107,7 @@ module PrettyText
|
|||
decorate_context(ctx)
|
||||
|
||||
ctx_load(ctx,
|
||||
"app/assets/javascripts/external/better_markdown.js",
|
||||
"vendor/assets/javascripts/better_markdown.js",
|
||||
"app/assets/javascripts/discourse/dialects/dialect.js",
|
||||
"app/assets/javascripts/discourse/components/utilities.js",
|
||||
"app/assets/javascripts/discourse/components/markdown.js")
|
||||
|
|
|
@ -14,13 +14,13 @@ test("avatarTemplate", function() {
|
|||
avatarSelector.get("gravatar_template"),
|
||||
"we are using gravatar by default");
|
||||
|
||||
avatarSelectorController.useUploadedAvatar();
|
||||
avatarSelectorController.send('useUploadedAvatar');
|
||||
|
||||
equal(avatarSelectorController.get("avatarTemplate"),
|
||||
avatarSelector.get("uploaded_avatar_template"),
|
||||
"calling useUploadedAvatar switches to using the uploaded avatar");
|
||||
|
||||
avatarSelectorController.useGravatar();
|
||||
avatarSelectorController.send('useGravatar');
|
||||
|
||||
equal(avatarSelectorController.get("avatarTemplate"),
|
||||
avatarSelector.get("gravatar_template"),
|
||||
|
|
|
@ -18,16 +18,16 @@ test("editingMode", function() {
|
|||
ok(!topicController.get('editingTopic'), "we are not editing by default");
|
||||
|
||||
topicController.set('model.details.can_edit', false);
|
||||
topicController.editTopic();
|
||||
topicController.send('editTopic');
|
||||
ok(!topicController.get('editingTopic'), "calling editTopic doesn't enable editing unless the user can edit");
|
||||
|
||||
topicController.set('model.details.can_edit', true);
|
||||
topicController.editTopic();
|
||||
topicController.send('editTopic');
|
||||
ok(topicController.get('editingTopic'), "calling editTopic enables editing if the user can edit");
|
||||
equal(topicController.get('newTitle'), topic.get('title'));
|
||||
equal(topicController.get('newCategoryId'), topic.get('category_id'));
|
||||
|
||||
topicController.cancelEditingTopic();
|
||||
topicController.send('cancelEditingTopic');
|
||||
ok(!topicController.get('editingTopic'), "cancelling edit mode reverts the property value");
|
||||
});
|
||||
|
||||
|
@ -43,12 +43,12 @@ test("toggledSelectedPost", function() {
|
|||
equal(tc.get('selectedPostsCount'), 0, "there is a selected post count of 0");
|
||||
ok(!tc.postSelected(post), "the post is not selected by default");
|
||||
|
||||
tc.toggledSelectedPost(post);
|
||||
tc.send('toggledSelectedPost', post);
|
||||
present(tc.get('selectedPosts'), "there is a selectedPosts collection");
|
||||
equal(tc.get('selectedPostsCount'), 1, "there is a selected post now");
|
||||
ok(tc.postSelected(post), "the post is now selected");
|
||||
|
||||
tc.toggledSelectedPost(post);
|
||||
tc.send('toggledSelectedPost', post);
|
||||
ok(!tc.postSelected(post), "the post is no longer selected");
|
||||
|
||||
});
|
||||
|
@ -61,10 +61,10 @@ test("selectAll", function() {
|
|||
postStream.appendPost(post);
|
||||
|
||||
ok(!tc.postSelected(post), "the post is not selected by default");
|
||||
tc.selectAll();
|
||||
tc.send('selectAll');
|
||||
ok(tc.postSelected(post), "the post is now selected");
|
||||
ok(tc.get('allPostsSelected'), "all posts are selected");
|
||||
tc.deselectAll();
|
||||
tc.send('deselectAll');
|
||||
ok(!tc.postSelected(post), "the post is deselected again");
|
||||
ok(!tc.get('allPostsSelected'), "all posts are not selected");
|
||||
|
||||
|
@ -80,10 +80,10 @@ test("Automating setting of allPostsSelected", function() {
|
|||
postStream.appendPost(post);
|
||||
ok(!tc.get('allPostsSelected'), "all posts are not selected by default");
|
||||
|
||||
tc.toggledSelectedPost(post);
|
||||
tc.send('toggledSelectedPost', post);
|
||||
ok(tc.get('allPostsSelected'), "all posts are selected if we select the only post");
|
||||
|
||||
tc.toggledSelectedPost(post);
|
||||
tc.send('toggledSelectedPost', post);
|
||||
ok(!tc.get('allPostsSelected'), "the posts are no longer automatically selected");
|
||||
});
|
||||
|
||||
|
@ -96,20 +96,20 @@ test("Select Replies when present", function() {
|
|||
postStream = tc.get('postStream');
|
||||
|
||||
ok(!tc.postSelected(p3), "replies are not selected by default");
|
||||
tc.toggledSelectedPostReplies(p1);
|
||||
tc.send('toggledSelectedPostReplies', p1);
|
||||
ok(tc.postSelected(p1), "it selects the post");
|
||||
ok(!tc.postSelected(p2), "it doesn't select a post that's not a reply");
|
||||
ok(tc.postSelected(p3), "it selects a post that is a reply");
|
||||
equal(tc.get('selectedPostsCount'), 2, "it has a selected posts count of two");
|
||||
|
||||
// If we deselected the post whose replies are selected...
|
||||
tc.toggledSelectedPost(p1);
|
||||
tc.send('toggledSelectedPost', p1);
|
||||
ok(!tc.postSelected(p1), "it deselects the post");
|
||||
ok(!tc.postSelected(p3), "it deselects the replies too");
|
||||
|
||||
// If we deselect a reply, it should deselect the parent's replies selected attribute. Weird but what else would make sense?
|
||||
tc.toggledSelectedPostReplies(p1);
|
||||
tc.toggledSelectedPost(p3);
|
||||
tc.send('toggledSelectedPostReplies', p1);
|
||||
tc.send('toggledSelectedPost', p3);
|
||||
ok(tc.postSelected(p1), "the post stays selected");
|
||||
ok(!tc.postSelected(p3), "it deselects the replies too");
|
||||
|
||||
|
|
|
@ -184,7 +184,5 @@ var jsHintOpts = {
|
|||
<%= jshint("#{Rails.root}/app/assets/javascripts/**/*.js",
|
||||
"/app/assets/javascripts/",
|
||||
[/external\//,
|
||||
/external_development\//,
|
||||
/external_production\//,
|
||||
/defer\//,
|
||||
/locales\//]) %>
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
//= require ../../app/assets/javascripts/discourse/components/probes.js
|
||||
|
||||
// Externals we need to load first
|
||||
//= require ../../app/assets/javascripts/external_development/jquery-2.0.3.js
|
||||
//= require ../../app/assets/javascripts/external/jquery.ui.widget.js
|
||||
//= require ../../app/assets/javascripts/external/handlebars.js
|
||||
//= require ../../app/assets/javascripts/external_development/ember.js
|
||||
//= require development/jquery-2.0.3.js
|
||||
//= require jquery.ui.widget.js
|
||||
//= require handlebars.js
|
||||
//= require development/ember.js
|
||||
|
||||
//= require ../../app/assets/javascripts/locales/i18n
|
||||
//= require ../../app/assets/javascripts/discourse/helpers/i18n_helpers
|
||||
|
@ -21,8 +21,36 @@
|
|||
// Pagedown customizations
|
||||
//= require ../../app/assets/javascripts/pagedown_custom.js
|
||||
|
||||
// The rest of the externals
|
||||
//= require_tree ../../app/assets/javascripts/external
|
||||
// The rest of the vendored JS
|
||||
//= require LAB.js
|
||||
//= require Markdown.Converter.js
|
||||
//= require Markdown.Editor.js
|
||||
//= require Markdown.Sanitizer.js
|
||||
//= require better_markdown.js
|
||||
//= require bootbox.js
|
||||
//= require bootstrap-alert.js
|
||||
//= require bootstrap-button.js
|
||||
//= require bootstrap-dropdown.js
|
||||
//= require bootstrap-modal.js
|
||||
//= require bootstrap-transition.js
|
||||
//= require browser-update.js
|
||||
//= require chosen.jquery.js
|
||||
//= require ember-renderspeed.js
|
||||
//= require favcount.js
|
||||
//= require jquery.ba-replacetext.js
|
||||
//= require jquery.ba-resize.min.js
|
||||
//= require jquery.color.js
|
||||
//= require jquery.cookie.js
|
||||
//= require jquery.fileupload.js
|
||||
//= require jquery.iframe-transport.js
|
||||
//= require jquery.putcursoratend.js
|
||||
//= require jquery.tagsinput.js
|
||||
//= require lodash.js
|
||||
//= require md5.js
|
||||
//= require modernizr.custom.95264.js
|
||||
//= require mousetrap.js
|
||||
//= require rsvp.js
|
||||
//= require show-html.js
|
||||
|
||||
// Stuff we need to load first
|
||||
//= require main_include
|
||||
|
|
12384
app/assets/javascripts/external_production/ember.js → vendor/assets/javascripts/development/ember.js
vendored
Normal file → Executable file
12384
app/assets/javascripts/external_production/ember.js → vendor/assets/javascripts/development/ember.js
vendored
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
314
vendor/assets/javascripts/list_view.js → vendor/assets/javascripts/development/list-view.js
vendored
Executable file → Normal file
314
vendor/assets/javascripts/list_view.js → vendor/assets/javascripts/development/list-view.js
vendored
Executable file → Normal file
|
@ -1,3 +1,6 @@
|
|||
// Last commit: 1f0c355 (2013-09-18 11:01:11 -0400)
|
||||
|
||||
|
||||
(function() {
|
||||
var get = Ember.get, set = Ember.set;
|
||||
|
||||
|
@ -18,7 +21,7 @@ function positionElement() {
|
|||
// TODO: avoid needing this by avoiding unnecessary
|
||||
// calls to this method in the first place
|
||||
if (samePosition(position, _position)) { return; }
|
||||
this._parentView.applyTransform(element, position);
|
||||
this._parentView.applyTransform(element, position.x, position.y);
|
||||
|
||||
this._position = position;
|
||||
}, this);
|
||||
|
@ -186,23 +189,54 @@ Ember.ReusableListItemView = Ember.View.extend(Ember.ListItemViewMixin, {
|
|||
|
||||
|
||||
(function() {
|
||||
var el = document.createElement('div'), style = el.style;
|
||||
|
||||
var propPrefixes = ['Webkit', 'Moz', 'O', 'ms'];
|
||||
|
||||
function testProp(prop) {
|
||||
if (prop in style) return prop;
|
||||
var uppercaseProp = prop.charAt(0).toUpperCase() + prop.slice(1);
|
||||
for (var i=0; i<propPrefixes.length; i++) {
|
||||
var prefixedProp = propPrefixes[i] + uppercaseProp;
|
||||
if (prefixedProp in style) {
|
||||
return prefixedProp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var transformProp = testProp('transform');
|
||||
var perspectiveProp = testProp('perspective');
|
||||
|
||||
var supports2D = transformProp !== null;
|
||||
var supports3D = perspectiveProp !== null;
|
||||
|
||||
Ember.ListViewHelper = {
|
||||
transformProp: transformProp,
|
||||
applyTransform: (function(){
|
||||
var element = document.createElement('div');
|
||||
|
||||
if ('webkitTransform' in element.style){
|
||||
return function(element, position){
|
||||
var x = position.x,
|
||||
y = position.y;
|
||||
|
||||
element.style.webkitTransform = 'translate3d(' + x + 'px, ' + y + 'px, 0)';
|
||||
if (supports2D) {
|
||||
return function(element, x, y){
|
||||
element.style[transformProp] = 'translate(' + x + 'px, ' + y + 'px)';
|
||||
};
|
||||
}else{
|
||||
return function(element, position){
|
||||
var x = position.x,
|
||||
y = position.y;
|
||||
|
||||
element.style.top = y + 'px';
|
||||
} else {
|
||||
return function(element, x, y){
|
||||
element.style.top = y + 'px';
|
||||
element.style.left = x + 'px';
|
||||
};
|
||||
}
|
||||
})(),
|
||||
apply3DTransform: (function(){
|
||||
if (supports3D) {
|
||||
return function(element, x, y){
|
||||
element.style[transformProp] = 'translate3d(' + x + 'px, ' + y + 'px, 0)';
|
||||
};
|
||||
} else if (supports2D) {
|
||||
return function(element, x, y){
|
||||
element.style[transformProp] = 'translate(' + x + 'px, ' + y + 'px)';
|
||||
};
|
||||
} else {
|
||||
return function(element, x, y){
|
||||
element.style.top = y + 'px';
|
||||
element.style.left = x + 'px';
|
||||
};
|
||||
}
|
||||
|
@ -239,10 +273,6 @@ function sortByContentIndex (viewOne, viewTwo){
|
|||
return get(viewOne, 'contentIndex') - get(viewTwo, 'contentIndex');
|
||||
}
|
||||
|
||||
function detectListItemViews(childView) {
|
||||
return Ember.ListItemViewMixin.detect(childView);
|
||||
}
|
||||
|
||||
function notifyMutationListeners() {
|
||||
if (Ember.View.notifyMutationListeners) {
|
||||
Ember.run.once(Ember.View, 'notifyMutationListeners');
|
||||
|
@ -296,6 +326,7 @@ function enableProfilingOutput() {
|
|||
*/
|
||||
Ember.ListViewMixin = Ember.Mixin.create({
|
||||
itemViewClass: Ember.ListItemView,
|
||||
emptyViewClass: Ember.View,
|
||||
classNames: ['ember-list-view'],
|
||||
attributeBindings: ['style'],
|
||||
domManager: domManager,
|
||||
|
@ -315,13 +346,16 @@ Ember.ListViewMixin = Ember.Mixin.create({
|
|||
*/
|
||||
init: function() {
|
||||
this._super();
|
||||
enableProfilingOutput();
|
||||
addContentArrayObserver.call(this);
|
||||
this._syncChildViews();
|
||||
this.columnCountDidChange();
|
||||
this.on('didInsertElement', syncListContainerWidth);
|
||||
this.columnCountDidChange();
|
||||
this._syncChildViews();
|
||||
this._addContentArrayObserver();
|
||||
},
|
||||
|
||||
_addContentArrayObserver: Ember.beforeObserver(function() {
|
||||
addContentArrayObserver.call(this);
|
||||
}, 'content'),
|
||||
|
||||
/**
|
||||
Called on your view when it should push strings of HTML into a
|
||||
`Ember.RenderBuffer`.
|
||||
|
@ -599,7 +633,7 @@ Ember.ListViewMixin = Ember.Mixin.create({
|
|||
maxScrollTop: Ember.computed('height', 'totalHeight', function(){
|
||||
var totalHeight, viewportHeight;
|
||||
|
||||
totalHeight = get(this, 'totalHeight'),
|
||||
totalHeight = get(this, 'totalHeight');
|
||||
viewportHeight = get(this, 'height');
|
||||
|
||||
return max(0, totalHeight - viewportHeight);
|
||||
|
@ -665,7 +699,7 @@ Ember.ListViewMixin = Ember.Mixin.create({
|
|||
}
|
||||
}, 'content'),
|
||||
|
||||
/**
|
||||
/**),
|
||||
@private
|
||||
@event contentDidChange
|
||||
*/
|
||||
|
@ -768,7 +802,7 @@ Ember.ListViewMixin = Ember.Mixin.create({
|
|||
scrollTop = get(this, 'scrollTop');
|
||||
contentLength = get(this, 'content.length');
|
||||
maxContentIndex = max(contentLength - 1, 0);
|
||||
childViews = get(this, 'listItemViews');
|
||||
childViews = this._childViews;
|
||||
childViewsLength = childViews.length;
|
||||
|
||||
startingIndex = this._startingIndex();
|
||||
|
@ -786,24 +820,12 @@ Ember.ListViewMixin = Ember.Mixin.create({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@private
|
||||
|
||||
Returns an array of current ListItemView views in the visible area
|
||||
when you start to scroll.
|
||||
|
||||
@property {Ember.ComputedProperty} listItemViews
|
||||
*/
|
||||
listItemViews: Ember.computed('[]', function(){
|
||||
return this.filter(detectListItemViews);
|
||||
}),
|
||||
|
||||
/**
|
||||
@private
|
||||
@method positionOrderedChildViews
|
||||
*/
|
||||
positionOrderedChildViews: function() {
|
||||
return get(this, 'listItemViews').sort(sortByContentIndex);
|
||||
return this._childViews.sort(sortByContentIndex);
|
||||
},
|
||||
|
||||
arrayWillChange: Ember.K,
|
||||
|
@ -944,13 +966,7 @@ Ember.ListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
'overflow-scrolling': 'touch'
|
||||
},
|
||||
|
||||
applyTransform: function(element, position){
|
||||
var x = position.x,
|
||||
y = position.y;
|
||||
|
||||
element.style.top = y + 'px';
|
||||
element.style.left = x + 'px';
|
||||
},
|
||||
applyTransform: Ember.ListViewHelper.applyTransform,
|
||||
|
||||
_scrollTo: function(scrollTop) {
|
||||
var element = get(this, 'element');
|
||||
|
@ -1006,6 +1022,148 @@ Ember.ListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
|
||||
|
||||
|
||||
(function() {
|
||||
var fieldRegex = /input|textarea|select/i,
|
||||
hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch,
|
||||
handleStart, handleMove, handleEnd, handleCancel,
|
||||
startEvent, moveEvent, endEvent, cancelEvent;
|
||||
if (hasTouch) {
|
||||
startEvent = 'touchstart';
|
||||
handleStart = function (e) {
|
||||
var touch = e.touches[0],
|
||||
target = touch && touch.target;
|
||||
// avoid e.preventDefault() on fields
|
||||
if (target && fieldRegex.test(target.tagName)) {
|
||||
return;
|
||||
}
|
||||
bindWindow(this.scrollerEventHandlers);
|
||||
this.willBeginScroll(e.touches, e.timeStamp);
|
||||
e.preventDefault();
|
||||
};
|
||||
moveEvent = 'touchmove';
|
||||
handleMove = function (e) {
|
||||
this.continueScroll(e.touches, e.timeStamp);
|
||||
};
|
||||
endEvent = 'touchend';
|
||||
handleEnd = function (e) {
|
||||
// if we didn't end up scrolling we need to
|
||||
// synthesize click since we did e.preventDefault()
|
||||
// on touchstart
|
||||
if (!this._isScrolling) {
|
||||
synthesizeClick(e);
|
||||
}
|
||||
unbindWindow(this.scrollerEventHandlers);
|
||||
this.endScroll(e.timeStamp);
|
||||
};
|
||||
cancelEvent = 'touchcancel';
|
||||
handleCancel = function (e) {
|
||||
unbindWindow(this.scrollerEventHandlers);
|
||||
this.endScroll(e.timeStamp);
|
||||
};
|
||||
} else {
|
||||
startEvent = 'mousedown';
|
||||
handleStart = function (e) {
|
||||
if (e.which !== 1) return;
|
||||
var target = e.target;
|
||||
// avoid e.preventDefault() on fields
|
||||
if (target && fieldRegex.test(target.tagName)) {
|
||||
return;
|
||||
}
|
||||
bindWindow(this.scrollerEventHandlers);
|
||||
this.willBeginScroll([e], e.timeStamp);
|
||||
e.preventDefault();
|
||||
};
|
||||
moveEvent = 'mousemove';
|
||||
handleMove = function (e) {
|
||||
this.continueScroll([e], e.timeStamp);
|
||||
};
|
||||
endEvent = 'mouseup';
|
||||
handleEnd = function (e) {
|
||||
unbindWindow(this.scrollerEventHandlers);
|
||||
this.endScroll(e.timeStamp);
|
||||
};
|
||||
cancelEvent = 'mouseout';
|
||||
handleCancel = function (e) {
|
||||
if (e.relatedTarget) return;
|
||||
unbindWindow(this.scrollerEventHandlers);
|
||||
this.endScroll(e.timeStamp);
|
||||
};
|
||||
}
|
||||
|
||||
function handleWheel(e) {
|
||||
this.mouseWheel(e);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function bindElement(el, handlers) {
|
||||
el.addEventListener(startEvent, handlers.start, false);
|
||||
el.addEventListener('mousewheel', handlers.wheel, false);
|
||||
}
|
||||
|
||||
function unbindElement(el, handlers) {
|
||||
el.removeEventListener(startEvent, handlers.start, false);
|
||||
el.removeEventListener('mousewheel', handlers.wheel, false);
|
||||
}
|
||||
|
||||
function bindWindow(handlers) {
|
||||
window.addEventListener(moveEvent, handlers.move, true);
|
||||
window.addEventListener(endEvent, handlers.end, true);
|
||||
window.addEventListener(cancelEvent, handlers.cancel, true);
|
||||
}
|
||||
|
||||
function unbindWindow(handlers) {
|
||||
window.removeEventListener(moveEvent, handlers.move, true);
|
||||
window.removeEventListener(endEvent, handlers.end, true);
|
||||
window.removeEventListener(cancelEvent, handlers.cancel, true);
|
||||
}
|
||||
|
||||
Ember.VirtualListScrollerEvents = Ember.Mixin.create({
|
||||
init: function() {
|
||||
this.on('didInsertElement', this, 'bindScrollerEvents');
|
||||
this.on('willDestroyElement', this, 'unbindScrollerEvents');
|
||||
this.scrollerEventHandlers = {
|
||||
start: bind(this, handleStart),
|
||||
move: bind(this, handleMove),
|
||||
end: bind(this, handleEnd),
|
||||
cancel: bind(this, handleCancel),
|
||||
wheel: bind(this, handleWheel)
|
||||
};
|
||||
return this._super();
|
||||
},
|
||||
bindScrollerEvents: function() {
|
||||
var el = this.get('element'),
|
||||
handlers = this.scrollerEventHandlers;
|
||||
bindElement(el, handlers);
|
||||
},
|
||||
unbindScrollerEvents: function() {
|
||||
var el = this.get('element'),
|
||||
handlers = this.scrollerEventHandlers;
|
||||
unbindElement(el, handlers);
|
||||
unbindWindow(handlers);
|
||||
}
|
||||
});
|
||||
|
||||
function bind(view, handler) {
|
||||
return function (evt) {
|
||||
handler.call(view, evt);
|
||||
};
|
||||
}
|
||||
|
||||
function synthesizeClick(e) {
|
||||
var point = e.changedTouches[0],
|
||||
target = point.target,
|
||||
ev;
|
||||
if (target && fieldRegex.test(target.tagName)) {
|
||||
ev = document.createEvent('MouseEvents');
|
||||
ev.initMouseEvent('click', true, true, e.view, 1, point.screenX, point.screenY, point.clientX, point.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 0, null);
|
||||
return target.dispatchEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
/*global Scroller*/
|
||||
var max = Math.max, get = Ember.get, set = Ember.set;
|
||||
|
@ -1029,8 +1187,9 @@ function updateScrollerDimensions(target) {
|
|||
@class VirtualListView
|
||||
@namespace Ember
|
||||
*/
|
||||
Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
||||
Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, Ember.VirtualListScrollerEvents, {
|
||||
_isScrolling: false,
|
||||
_mouseWheel: null,
|
||||
css: {
|
||||
position: 'relative',
|
||||
overflow: 'hidden'
|
||||
|
@ -1041,7 +1200,7 @@ Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
this.setupScroller();
|
||||
},
|
||||
_scrollerTop: 0,
|
||||
applyTransform: Ember.ListViewHelper.applyTransform,
|
||||
applyTransform: Ember.ListViewHelper.apply3DTransform,
|
||||
|
||||
setupScroller: function(){
|
||||
var view, y;
|
||||
|
@ -1052,7 +1211,7 @@ Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
if (view.state !== 'inDOM') { return; }
|
||||
|
||||
if (view.listContainerElement) {
|
||||
view.applyTransform(view.listContainerElement, {x: 0, y: -top});
|
||||
view.applyTransform(view.listContainerElement, 0, -top);
|
||||
view._scrollerTop = top;
|
||||
view._scrollContentTo(top);
|
||||
}
|
||||
|
@ -1072,17 +1231,7 @@ Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
}, 'width', 'height', 'totalHeight'),
|
||||
|
||||
didInsertElement: function() {
|
||||
var that, listContainerElement;
|
||||
|
||||
that = this;
|
||||
this.listContainerElement = this.$('> .ember-list-container')[0];
|
||||
|
||||
this._mouseWheel = function(e) { that.mouseWheel(e); };
|
||||
this.$().on('mousewheel', this._mouseWheel);
|
||||
},
|
||||
|
||||
willDestroyElement: function() {
|
||||
this.$().off('mousewheel', this._mouseWheel);
|
||||
},
|
||||
|
||||
willBeginScroll: function(touches, timeStamp) {
|
||||
|
@ -1113,6 +1262,10 @@ Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
}
|
||||
},
|
||||
|
||||
endScroll: function(timeStamp) {
|
||||
this.scroller.doTouchEnd(timeStamp);
|
||||
},
|
||||
|
||||
// api
|
||||
scrollTo: function(y, animate) {
|
||||
if (animate === undefined) {
|
||||
|
@ -1134,48 +1287,6 @@ Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
this.scroller.scrollBy(0, delta, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
endScroll: function(timeStamp) {
|
||||
this.scroller.doTouchEnd(timeStamp);
|
||||
},
|
||||
|
||||
touchStart: function(e){
|
||||
e = e.originalEvent || e;
|
||||
this.willBeginScroll(e.touches, e.timeStamp);
|
||||
return false;
|
||||
},
|
||||
|
||||
touchMove: function(e){
|
||||
e = e.originalEvent || e;
|
||||
this.continueScroll(e.touches, e.timeStamp);
|
||||
return false;
|
||||
},
|
||||
|
||||
touchEnd: function(e){
|
||||
e = e.originalEvent || e;
|
||||
this.endScroll(e.timeStamp);
|
||||
return false;
|
||||
},
|
||||
|
||||
mouseDown: function(e){
|
||||
this.willBeginScroll([e], e.timeStamp);
|
||||
return false;
|
||||
},
|
||||
|
||||
mouseMove: function(e){
|
||||
this.continueScroll([e], e.timeStamp);
|
||||
return false;
|
||||
},
|
||||
|
||||
mouseUp: function(e){
|
||||
this.endScroll(e.timeStamp);
|
||||
return false;
|
||||
},
|
||||
|
||||
mouseLeave: function(e){
|
||||
this.endScroll(e.timeStamp);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
@ -1187,3 +1298,4 @@ Ember.VirtualListView = Ember.ContainerView.extend(Ember.ListViewMixin, {
|
|||
(function() {
|
||||
|
||||
})();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue