mirror of
https://github.com/discourse/discourse.git
synced 2024-11-28 03:33:58 -06:00
Merge pull request #2141 from riking/correctness
Lots of JS correctness fixes
This commit is contained in:
commit
51e3d72461
@ -25,7 +25,7 @@ Discourse.AdminApiController = Ember.ArrayController.extend({
|
||||
Creates an API key instance with internal user object
|
||||
|
||||
@method regenerateKey
|
||||
@param {Discourse.ApiKey} the key to regenerate
|
||||
@param {Discourse.ApiKey} key the key to regenerate
|
||||
**/
|
||||
regenerateKey: function(key) {
|
||||
bootbox.confirm(I18n.t("admin.api.confirm_regen"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
||||
@ -39,7 +39,7 @@ Discourse.AdminApiController = Ember.ArrayController.extend({
|
||||
Revokes an API key
|
||||
|
||||
@method revokeKey
|
||||
@param {Discourse.ApiKey} the key to revoke
|
||||
@param {Discourse.ApiKey} key the key to revoke
|
||||
**/
|
||||
revokeKey: function(key) {
|
||||
var self = this;
|
||||
|
@ -1,5 +1,5 @@
|
||||
Discourse.AdminBackupsController = Ember.ObjectController.extend({
|
||||
noOperationIsRunning: Em.computed.not("isOperationRunning"),
|
||||
rollbackEnabled: Em.computed.and("canRollback", "restoreEnabled", "noOperationIsRunning"),
|
||||
rollbackDisabled: Em.computed.not("rollbackEnabled"),
|
||||
rollbackDisabled: Em.computed.not("rollbackEnabled")
|
||||
});
|
||||
|
@ -71,6 +71,5 @@ Discourse.AdminBackupsIndexController = Ember.ArrayController.extend({
|
||||
}).then(function() {
|
||||
Discourse.set("isReadOnly", enable);
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
Discourse.AdminBackupsLogsController = Ember.ArrayController.extend({
|
||||
needs: ["adminBackups"],
|
||||
status: Em.computed.alias("controllers.adminBackups"),
|
||||
status: Em.computed.alias("controllers.adminBackups")
|
||||
});
|
||||
|
@ -13,8 +13,7 @@ Discourse.AdminEmailSentController = Discourse.Controller.extend({
|
||||
Discourse.EmailLog.findAll(this.get("filter")).then(function(logs) {
|
||||
self.set("model", logs);
|
||||
});
|
||||
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.reply_key"),
|
||||
|
||||
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.reply_key")
|
||||
});
|
||||
|
||||
/**
|
||||
@ -32,8 +31,7 @@ Discourse.AdminEmailSkippedController = Discourse.Controller.extend({
|
||||
Discourse.EmailLog.findAll(this.get("filter")).then(function(logs) {
|
||||
self.set("model", logs);
|
||||
});
|
||||
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.skipped_reason"),
|
||||
|
||||
}, 250).observes("filter.user", "filter.address", "filter.type", "filter.skipped_reason")
|
||||
});
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ Discourse.ApiKey.reopenClass({
|
||||
Creates an API key instance with internal user object
|
||||
|
||||
@method create
|
||||
@param {Object} the properties to create
|
||||
@param {...} var_args the properties to initialize this with
|
||||
@returns {Discourse.ApiKey} the ApiKey instance
|
||||
**/
|
||||
create: function() {
|
||||
|
@ -85,6 +85,5 @@ Discourse.Backup.reopenClass({
|
||||
window.location.pathname = Discourse.getURL("/");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -12,6 +12,5 @@ Discourse.BackupStatus = Discourse.Model.extend({
|
||||
|
||||
restoreEnabled: function() {
|
||||
return Discourse.SiteSettings.allow_restore && !this.get("isOperationRunning");
|
||||
}.property("isOperationRunning"),
|
||||
|
||||
}.property("isOperationRunning")
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ Discourse.AdminBackupsRoute = Discourse.Route.extend({
|
||||
}).then(function (status) {
|
||||
return Discourse.BackupStatus.create({
|
||||
isOperationRunning: status.is_operation_running,
|
||||
canRollback: status.can_rollback,
|
||||
canRollback: status.can_rollback
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -69,7 +69,7 @@ Discourse.AdminBackupsRoute = Discourse.Route.extend({
|
||||
Destroys a backup
|
||||
|
||||
@method destroyBackup
|
||||
@param {Discourse.Backup} the backup to destroy
|
||||
@param {Discourse.Backup} backup the backup to destroy
|
||||
**/
|
||||
destroyBackup: function(backup) {
|
||||
var self = this;
|
||||
@ -91,7 +91,7 @@ Discourse.AdminBackupsRoute = Discourse.Route.extend({
|
||||
Start a restore and redirect the user to the logs tab
|
||||
|
||||
@method startRestore
|
||||
@param {Discourse.Backup} the backup to restore
|
||||
@param {Discourse.Backup} backup the backup to restore
|
||||
**/
|
||||
startRestore: function(backup) {
|
||||
var self = this;
|
||||
@ -160,7 +160,6 @@ Discourse.AdminBackupsRoute = Discourse.Route.extend({
|
||||
|
||||
uploadError: function(filename, message) {
|
||||
bootbox.alert(I18n.t("admin.backups.upload.error", { filename: filename, message: message }));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -22,7 +22,7 @@ Discourse.AdminCustomizeView = Discourse.View.extend({
|
||||
selectStylesheet: function() { this.set('selected', 'stylesheet'); },
|
||||
|
||||
selectMobileHeader: function() { this.set('selected', 'mobileHeader'); },
|
||||
selectMobileStylesheet: function() { this.set('selected', 'mobileStylesheet'); },
|
||||
selectMobileStylesheet: function() { this.set('selected', 'mobileStylesheet'); }
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
|
@ -8,7 +8,7 @@ Discourse.AutoCloseFormComponent = Ember.Component.extend({
|
||||
|
||||
autoCloseChanged: function() {
|
||||
if( this.get('autoCloseTime') && this.get('autoCloseTime').length > 0 ) {
|
||||
this.set('autoCloseTime', this.get('autoCloseTime').replace(/[^\d-\s\:]/g, '') );
|
||||
this.set('autoCloseTime', this.get('autoCloseTime').replace(/[^:\d-\s]/g, '') );
|
||||
}
|
||||
this.set('autoCloseValid', this.isAutoCloseValid());
|
||||
}.observes('autoCloseTime'),
|
||||
|
@ -20,5 +20,5 @@ Discourse.DiscoveryController = Discourse.ObjectController.extend({
|
||||
showMoreDailyUrl: function() { return this.showMoreUrl('daily'); }.property('category', 'noSubcategories'),
|
||||
showMoreWeeklyUrl: function() { return this.showMoreUrl('weekly'); }.property('category', 'noSubcategories'),
|
||||
showMoreMonthlyUrl: function() { return this.showMoreUrl('monthly'); }.property('category', 'noSubcategories'),
|
||||
showMoreYearlyUrl: function() { return this.showMoreUrl('yearly'); }.property('category', 'noSubcategories'),
|
||||
showMoreYearlyUrl: function() { return this.showMoreUrl('yearly'); }.property('category', 'noSubcategories')
|
||||
});
|
||||
|
@ -12,6 +12,6 @@ Discourse.GroupController = Discourse.ObjectController.extend({
|
||||
// It would be nice if bootstrap marked action lists as selected when their links
|
||||
// were 'active' not the `li` tags.
|
||||
showingIndex: Em.computed.equal('showing', 'index'),
|
||||
showingMembers: Em.computed.equal('showing', 'members'),
|
||||
showingMembers: Em.computed.equal('showing', 'members')
|
||||
});
|
||||
|
||||
|
@ -44,8 +44,7 @@ Discourse.UserInvitedController = Ember.ArrayController.extend({
|
||||
@property showSearch
|
||||
**/
|
||||
showSearch: function() {
|
||||
if (Em.isNone(this.get('searchTerm')) && this.get('model.length') === 0) { return false; }
|
||||
return true;
|
||||
return !(Em.isNone(this.get('searchTerm')) && this.get('model.length') === 0);
|
||||
}.property('searchTerm', 'model.length'),
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,14 @@
|
||||
@method replaceBBCode
|
||||
@param {tag} tag the tag we want to match
|
||||
@param {function} emitter the function that creates JsonML for the tag
|
||||
@param {Object} hash of options to pass to `inlineBetween`
|
||||
@param {Object} opts options to pass to Discourse.Dialect.inlineBetween
|
||||
@param {Function} [opts.emitter] The function that will be called with the contents and returns JsonML.
|
||||
@param {String} [opts.start] The starting token we want to find
|
||||
@param {String} [opts.stop] The ending token we want to find
|
||||
@param {String} [opts.between] A shortcut for when the `start` and `stop` are the same.
|
||||
@param {Boolean} [opts.rawContents] If true, the contents between the tokens will not be parsed.
|
||||
@param {Boolean} [opts.wordBoundary] If true, the match must be on a word boundary
|
||||
@param {Boolean} [opts.spaceBoundary] If true, the match must be on a sppace boundary
|
||||
**/
|
||||
function replaceBBCode(tag, emitter, opts) {
|
||||
opts = opts || {};
|
||||
|
@ -120,10 +120,10 @@ function parseTree(tree, path, insideCounts) {
|
||||
**/
|
||||
function invalidBoundary(args, prev) {
|
||||
|
||||
if (!args.wordBoundary && !args.spaceBoundary) { return; }
|
||||
if (!args.wordBoundary && !args.spaceBoundary) { return false; }
|
||||
|
||||
var last = prev[prev.length - 1];
|
||||
if (typeof last !== "string") { return; }
|
||||
if (typeof last !== "string") { return false; }
|
||||
|
||||
if (args.wordBoundary && (last.match(/(\w|\/)$/))) { return true; }
|
||||
if (args.spaceBoundary && (!last.match(/\s$/))) { return true; }
|
||||
@ -143,15 +143,15 @@ Discourse.Dialect = {
|
||||
|
||||
@method cook
|
||||
@param {String} text the raw text to cook
|
||||
@param {Object} opts hash of options
|
||||
@returns {String} the cooked text
|
||||
**/
|
||||
cook: function(text, opts) {
|
||||
if (!initialized) { initializeDialects(); }
|
||||
dialect.options = opts;
|
||||
var tree = parser.toHTMLTree(text, 'Discourse'),
|
||||
html = parser.renderJsonML(parseTree(tree));
|
||||
var tree = parser.toHTMLTree(text, 'Discourse');
|
||||
|
||||
return html;
|
||||
return parser.renderJsonML(parseTree(tree));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -288,9 +288,8 @@ Discourse.Dialect = {
|
||||
the other helpers such as `replaceBlock` so consider using them first!
|
||||
|
||||
@method registerBlock
|
||||
@param {String} the name of the block handler
|
||||
@param {Function} the handler
|
||||
|
||||
@param {String} name the name of the block handler
|
||||
@param {Function} handler the handler
|
||||
**/
|
||||
registerBlock: function(name, handler) {
|
||||
dialect.block[name] = handler;
|
||||
|
@ -271,7 +271,7 @@ $.fn.autocomplete = function(options) {
|
||||
});
|
||||
|
||||
return $(this).keydown(function(e) {
|
||||
var c, caretPosition, i, initial, next, nextIsGood, prev, prevIsGood, stopFound, term, total, userToComplete;
|
||||
var c, caretPosition, i, initial, next, prev, prevIsGood, stopFound, term, total, userToComplete;
|
||||
|
||||
if(options.allowAny){
|
||||
// saves us wiring up a change event as well, keypress is while its pressed
|
||||
@ -298,7 +298,6 @@ $.fn.autocomplete = function(options) {
|
||||
if ((completeStart === null) && e.which === 8 && options.key) {
|
||||
c = Discourse.Utilities.caretPosition(me[0]);
|
||||
next = me[0].value[c];
|
||||
nextIsGood = next === void 0 || /\s/.test(next);
|
||||
c -= 1;
|
||||
initial = c;
|
||||
prevIsGood = true;
|
||||
|
@ -71,8 +71,6 @@ $.fn.caretPosition = function(options) {
|
||||
"line-height": important("line-height")
|
||||
});
|
||||
|
||||
before = void 0;
|
||||
after = void 0;
|
||||
pos = options && (options.pos || options.pos === 0) ? options.pos : getCaret(textarea[0]);
|
||||
val = textarea.val().replace("\r", "");
|
||||
if (options && options.key) {
|
||||
|
@ -110,6 +110,6 @@ Discourse.computed = {
|
||||
});
|
||||
});
|
||||
return computed.property.apply(computed, args);
|
||||
},
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -21,7 +21,6 @@ Discourse.Eyeline.prototype.update = function() {
|
||||
docViewBottom = docViewTop + windowHeight,
|
||||
$elements = $(this.selector),
|
||||
atBottom = false,
|
||||
foundElement = false,
|
||||
bottomOffset = $elements.last().offset(),
|
||||
self = this;
|
||||
|
||||
@ -29,9 +28,6 @@ Discourse.Eyeline.prototype.update = function() {
|
||||
atBottom = (bottomOffset.top <= docViewBottom) && (bottomOffset.top >= docViewTop);
|
||||
}
|
||||
|
||||
// Whether we've seen any elements in this search
|
||||
foundElement = false;
|
||||
|
||||
return $elements.each(function(i, elem) {
|
||||
var $elem = $(elem),
|
||||
elemTop = $elem.offset().top,
|
||||
|
@ -237,7 +237,7 @@ relativeAgeMediumSpan = function(distance, leaveAgo) {
|
||||
|
||||
relativeAgeMedium = function(date, options){
|
||||
var displayDate, fiveDaysAgo, oneMinuteAgo, fullReadable, leaveAgo;
|
||||
var wrapInSpan = options.wrapInSpan === false ? false : true;
|
||||
var wrapInSpan = options.wrapInSpan !== false;
|
||||
|
||||
leaveAgo = options.leaveAgo;
|
||||
var distance = Math.round((new Date() - date) / 1000);
|
||||
|
@ -13,10 +13,10 @@ Discourse.Markdown = {
|
||||
validIframes: [],
|
||||
|
||||
/**
|
||||
Whitelists classes for sanitization
|
||||
Whitelists more classes for sanitization.
|
||||
|
||||
@param {...String} var_args Classes to whitelist
|
||||
@method whiteListClass
|
||||
@param {String} val The value to whitelist. Can supply more than one argument
|
||||
**/
|
||||
whiteListClass: function() {
|
||||
var args = Array.prototype.slice.call(arguments),
|
||||
@ -113,7 +113,10 @@ Discourse.Markdown = {
|
||||
Checks to see if a URL is allowed in the cooked content
|
||||
|
||||
@method urlAllowed
|
||||
@param {String} url Url to check
|
||||
@param {String} uri Url to check
|
||||
@param {Number} effect ignored
|
||||
@param {Number} ltype ignored
|
||||
@param {Object} hints an object with hints, used to check if this url is from an iframe
|
||||
@return {String} url to insert in the cooked content
|
||||
**/
|
||||
urlAllowed: function (uri, effect, ltype, hints) {
|
||||
|
@ -14,7 +14,7 @@ Discourse.Mobile = {
|
||||
this.mobileView = $html.hasClass('mobile-view');
|
||||
|
||||
if (localStorage && localStorage.mobileView) {
|
||||
var savedValue = (localStorage.mobileView === 'true' ? true : false);
|
||||
var savedValue = (localStorage.mobileView === 'true');
|
||||
if (savedValue !== this.mobileView) {
|
||||
this.reloadPage(savedValue);
|
||||
}
|
||||
|
@ -22,7 +22,8 @@ Discourse.PageTracker = Ember.Object.extend(Ember.Evented, {
|
||||
self = this;
|
||||
|
||||
router.on('didTransition', function() {
|
||||
self.trigger('change', this.get('url'));
|
||||
var router = this;
|
||||
self.trigger('change', router.get('url'));
|
||||
});
|
||||
this.set('started', true);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ Discourse.UserSearch = {
|
||||
var promise = Ember.Deferred.create();
|
||||
|
||||
// TODO site setting for allowed regex in username
|
||||
if (term.match(/[^a-zA-Z0-9\_\.]/)) {
|
||||
if (term.match(/[^a-zA-Z0-9_\.]/)) {
|
||||
promise.resolve([]);
|
||||
return promise;
|
||||
}
|
||||
@ -54,8 +54,7 @@ Discourse.UserSearch = {
|
||||
users.push(u);
|
||||
results.push(u);
|
||||
}
|
||||
if (results.length > limit) return false;
|
||||
return true;
|
||||
return results.length <= limit;
|
||||
});
|
||||
|
||||
_.each(r.groups,function(g) {
|
||||
|
@ -210,7 +210,7 @@ Discourse.Utilities = {
|
||||
Check the extension of the file against the list of authorized extensions
|
||||
|
||||
@method isAuthorizedUpload
|
||||
@param {File} files The file we want to upload
|
||||
@param {File} file The file we want to upload
|
||||
**/
|
||||
isAuthorizedUpload: function(file) {
|
||||
var extensions = Discourse.SiteSettings.authorized_extensions;
|
||||
|
@ -13,7 +13,8 @@ Discourse.ModalFunctionality = Em.Mixin.create({
|
||||
Flash a message at the top of the modal
|
||||
|
||||
@method blank
|
||||
@param {String} name the name of the property we want to check
|
||||
@param {String} message I18n name of the message
|
||||
@param {String} messageClass CSS class to apply
|
||||
@return {Boolean}
|
||||
**/
|
||||
flash: function(message, messageClass) {
|
||||
|
@ -12,7 +12,6 @@ Discourse.ScrollTop = Em.Mixin.create({
|
||||
Em.run.schedule('afterRender', function() {
|
||||
$(document).scrollTop(0);
|
||||
});
|
||||
}.on('didInsertElement'),
|
||||
|
||||
}.on('didInsertElement')
|
||||
});
|
||||
|
||||
|
@ -66,7 +66,7 @@ Discourse.CategoryList.reopenClass({
|
||||
can_create_category: result.category_list.can_create_category,
|
||||
can_create_topic: result.category_list.can_create_topic,
|
||||
draft_key: result.category_list.draft_key,
|
||||
draft_sequence: result.category_list.draft_sequence,
|
||||
draft_sequence: result.category_list.draft_sequence
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -126,14 +126,10 @@ Discourse.Composer = Discourse.Model.extend({
|
||||
// reply is always required
|
||||
if (this.get('missingReplyCharacters') > 0) return true;
|
||||
|
||||
if (this.get('canCategorize') &&
|
||||
return this.get('canCategorize') &&
|
||||
!Discourse.SiteSettings.allow_uncategorized_topics &&
|
||||
!this.get('categoryId') &&
|
||||
!Discourse.User.currentProp('staff')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
!Discourse.User.currentProp('staff');
|
||||
}.property('loading', 'canEditTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryId', 'missingReplyCharacters'),
|
||||
|
||||
/**
|
||||
|
@ -103,11 +103,10 @@ Discourse.Post = Discourse.Model.extend({
|
||||
}.property('updated_at'),
|
||||
|
||||
flagsAvailable: function() {
|
||||
var post = this,
|
||||
flags = Discourse.Site.currentProp('flagTypes').filter(function(item) {
|
||||
var post = this;
|
||||
return Discourse.Site.currentProp('flagTypes').filter(function(item) {
|
||||
return post.get("actionByName." + (item.get('name_key')) + ".can_act");
|
||||
});
|
||||
return flags;
|
||||
}.property('actions_summary.@each.can_act'),
|
||||
|
||||
actionsHistory: function() {
|
||||
|
@ -179,7 +179,6 @@ Discourse.PostStream = Em.Object.extend({
|
||||
Cancel any active filters on the stream.
|
||||
|
||||
@method cancelFilter
|
||||
@returns {Ember.Deferred} a promise that resolves when the filter has been cancelled.
|
||||
**/
|
||||
cancelFilter: function() {
|
||||
this.set('summary', false);
|
||||
@ -373,8 +372,8 @@ Discourse.PostStream = Em.Object.extend({
|
||||
`undoPost` when it fails.
|
||||
|
||||
@method stagePost
|
||||
@param {Discourse.Post} the post to stage in the stream
|
||||
@param {Discourse.User} the user creating the post
|
||||
@param {Discourse.Post} post the post to stage in the stream
|
||||
@param {Discourse.User} user the user creating the post
|
||||
**/
|
||||
stagePost: function(post, user) {
|
||||
|
||||
|
@ -19,7 +19,7 @@ Discourse.TopList.reopenClass({
|
||||
can_create_topic: result.can_create_topic,
|
||||
draft: result.draft,
|
||||
draft_key: result.draft_key,
|
||||
draft_sequence: result.draft_sequence,
|
||||
draft_sequence: result.draft_sequence
|
||||
});
|
||||
|
||||
Discourse.Site.currentProp('periods').forEach(function(period) {
|
||||
|
@ -168,8 +168,7 @@ Discourse.Topic = Discourse.Model.extend({
|
||||
if (!wordCount) return;
|
||||
|
||||
// Avg for 500 words per minute when you account for skimming
|
||||
var minutes = Math.floor(wordCount / 500.0);
|
||||
return minutes;
|
||||
return Math.floor(wordCount / 500.0);
|
||||
}.property('word_count'),
|
||||
|
||||
toggleStar: function() {
|
||||
|
@ -162,7 +162,7 @@ Discourse.TopicList.reopenClass({
|
||||
Stitch together side loaded topic data
|
||||
|
||||
@method topicsFrom
|
||||
@param {Object} JSON object with topic data
|
||||
@param {Object} result JSON object with topic data
|
||||
@returns {Array} the list of topics
|
||||
**/
|
||||
topicsFrom: function(result) {
|
||||
@ -204,8 +204,8 @@ Discourse.TopicList.reopenClass({
|
||||
Lists topics on a given menu item
|
||||
|
||||
@method list
|
||||
@param {Object} The menu item to filter to
|
||||
@param {Object} Any additional params
|
||||
@param {Object} filter The menu item to filter to
|
||||
@param {Object} params Any additional params to pass to TopicList.find()
|
||||
@returns {Promise} a promise that resolves to the list of topics
|
||||
**/
|
||||
list: function(filter, params) {
|
||||
|
@ -461,6 +461,7 @@ Discourse.User.reopenClass(Discourse.Singleton, {
|
||||
@method checkUsername
|
||||
@param {String} username A username to check
|
||||
@param {String} email An email address to check
|
||||
@param {Number} forUserId user id - provide when changing username
|
||||
**/
|
||||
checkUsername: function(username, email, forUserId) {
|
||||
return Discourse.ajax('/users/check_username', {
|
||||
@ -472,7 +473,7 @@ Discourse.User.reopenClass(Discourse.Singleton, {
|
||||
Groups the user's statistics
|
||||
|
||||
@method groupStats
|
||||
@param {Array} Given stats
|
||||
@param {Array} stats Given stats
|
||||
@returns {Object}
|
||||
**/
|
||||
groupStats: function(stats) {
|
||||
@ -507,6 +508,7 @@ Discourse.User.reopenClass(Discourse.Singleton, {
|
||||
@param {String} name This user's name
|
||||
@param {String} email This user's email
|
||||
@param {String} password This user's password
|
||||
@param {String} username This user's username
|
||||
@param {String} passwordConfirm This user's confirmed password
|
||||
@param {String} challenge
|
||||
@returns Result of ajax call
|
||||
|
@ -45,5 +45,5 @@ Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend({
|
||||
}));
|
||||
this.controllerFor('editCategory').set('selectedTab', 'general');
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||
Discourse.PreferencesIndexRoute = Discourse.RestrictedUserRoute.extend({
|
||||
renderTemplate: function() {
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@
|
||||
<div class='controls'>
|
||||
<label class='radio'>
|
||||
<input type='radio' id="choose-topic-{{unbound id}}" name='choose_topic_id' {{action chooseTopic this target="view"}}>{{title}}
|
||||
</label>
|
||||
</div>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
@ -7,9 +7,9 @@
|
||||
</a>
|
||||
{{else}}
|
||||
{{#if noSubcategories}}
|
||||
<a href='#' {{action expand}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{i18n categories.no_subcategory}}</i></a>
|
||||
<a href='#' {{action expand}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{i18n categories.no_subcategory}}</a>
|
||||
{{else}}
|
||||
<a href='#' {{action expand}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{allCategoriesLabel}}</i></a>
|
||||
<a href='#' {{action expand}} class='badge-category home' {{bind-attr style="badgeStyle"}}>{{allCategoriesLabel}}</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<a href='#' {{action closeMessage this}} class='close'><i class='fa fa-times-circle'></i></a>
|
||||
<h3>{{i18n composer.similar_topics}}<h3>
|
||||
<h3>{{i18n composer.similar_topics}}</h3>
|
||||
|
||||
<ul class='topics'>
|
||||
{{#each similarTopics}}
|
||||
|
@ -47,6 +47,7 @@ Discourse.ActionsHistoryComponent = Em.Component.extend({
|
||||
var key = 'post.actions.people.' + c.get('actionType.name_key');
|
||||
if (postUrl) { key = key + "_with_url"; }
|
||||
|
||||
// TODO postUrl might be uninitialized? pick a good default
|
||||
buffer.push(" " + I18n.t(key, { icons: iconsHtml, postUrl: postUrl}) + ".");
|
||||
}
|
||||
renderActionIf('usersCollapsed', 'who-acted', c.get('description'));
|
||||
|
@ -504,7 +504,7 @@ Discourse.ComposerView = Discourse.View.extend(Ember.Evented, {
|
||||
var $uploadTarget = $('#reply-control');
|
||||
$uploadTarget.fileupload('destroy');
|
||||
$uploadTarget.off();
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
// not sure if this is the right way, keeping here for now, we could use a mixin perhaps
|
||||
|
@ -14,7 +14,7 @@ Discourse.ContainerView = Ember.ContainerView.extend(Discourse.Presence, {
|
||||
|
||||
@method attachViewWithArgs
|
||||
@param {Object} viewArgs The arguments to pass when creating the view
|
||||
@param {Class} klass The view class we want to create
|
||||
@param {Class} viewClass The view class we want to create
|
||||
**/
|
||||
attachViewWithArgs: function(viewArgs, viewClass) {
|
||||
if (!viewClass) { viewClass = Ember.View.extend(); }
|
||||
@ -26,7 +26,7 @@ Discourse.ContainerView = Ember.ContainerView.extend(Discourse.Presence, {
|
||||
Attaches a view with no arguments and wires up the container properly
|
||||
|
||||
@method attachViewClass
|
||||
@param {Class} klass The view class we want to create
|
||||
@param {Class} viewClass The view class we want to add
|
||||
**/
|
||||
attachViewClass: function(viewClass) {
|
||||
this.attachViewWithArgs(null, viewClass);
|
||||
|
@ -12,9 +12,10 @@ Discourse.ModalBodyView = Discourse.View.extend({
|
||||
didInsertElement: function() {
|
||||
var self = this;
|
||||
|
||||
$('#discourse-modal').modal('show');
|
||||
var $discourseModal = $('#discourse-modal');
|
||||
|
||||
$('#discourse-modal').one("hide", function () {
|
||||
$discourseModal.modal('show');
|
||||
$discourseModal.one("hide", function () {
|
||||
self.get("controller").send("closeModal");
|
||||
});
|
||||
|
||||
|
@ -207,7 +207,8 @@ Discourse.PostMenuView = Discourse.View.extend({
|
||||
}
|
||||
|
||||
buffer.push("<button title=\"" + tooltip +
|
||||
"\" data-action=\"bookmark\" class='bookmark'><div class='" + iconClass +
|
||||
"\" data-action=\"bookmark\" class='" + buttonClass +
|
||||
"'><div class='" + iconClass +
|
||||
"'></div></button>");
|
||||
},
|
||||
|
||||
|
@ -39,8 +39,9 @@ Discourse.ShareView = Discourse.View.extend({
|
||||
}.observes('controller.link'),
|
||||
|
||||
didInsertElement: function() {
|
||||
var shareView = this;
|
||||
$('html').on('mousedown.outside-share-link', function(e) {
|
||||
var shareView = this,
|
||||
$html = $('html');
|
||||
$html.on('mousedown.outside-share-link', function(e) {
|
||||
// Use mousedown instead of click so this event is handled before routing occurs when a
|
||||
// link is clicked (which is a click event) while the share dialog is showing.
|
||||
if (shareView.$().has(e.target).length !== 0) { return; }
|
||||
@ -49,9 +50,10 @@ Discourse.ShareView = Discourse.View.extend({
|
||||
return true;
|
||||
});
|
||||
|
||||
$('html').on('click.discoure-share-link', '[data-share-url]', function(e) {
|
||||
$html.on('click.discoure-share-link', '[data-share-url]', function(e) {
|
||||
e.preventDefault();
|
||||
var $currentTarget = $(e.currentTarget);
|
||||
var $currentTarget = $(e.currentTarget),
|
||||
$shareLink = $('#share-link');
|
||||
var url = $currentTarget.data('share-url');
|
||||
var postNumber = $currentTarget.data('post-number');
|
||||
// Relative urls
|
||||
@ -60,7 +62,7 @@ Discourse.ShareView = Discourse.View.extend({
|
||||
url = window.location.protocol + "//" + window.location.host + url;
|
||||
}
|
||||
|
||||
var shareLinkWidth = $('#share-link').width();
|
||||
var shareLinkWidth = $shareLink.width();
|
||||
var x = e.pageX - (shareLinkWidth / 2);
|
||||
if (x < 25) {
|
||||
x = 25;
|
||||
@ -70,12 +72,12 @@ Discourse.ShareView = Discourse.View.extend({
|
||||
}
|
||||
|
||||
var header = $('.d-header');
|
||||
var y = e.pageY - ($('#share-link').height() + 20);
|
||||
var y = e.pageY - ($shareLink.height() + 20);
|
||||
if (y < header.offset().top + header.height()) {
|
||||
y = e.pageY + 10;
|
||||
}
|
||||
|
||||
$('#share-link').css({
|
||||
$shareLink.css({
|
||||
left: "" + x + "px",
|
||||
top: "" + y + "px"
|
||||
});
|
||||
@ -84,7 +86,7 @@ Discourse.ShareView = Discourse.View.extend({
|
||||
return false;
|
||||
});
|
||||
|
||||
$('html').on('keydown.share-view', function(e){
|
||||
$html.on('keydown.share-view', function(e){
|
||||
if (e.keyCode === 27) {
|
||||
shareView.get('controller').send('close');
|
||||
}
|
||||
@ -92,9 +94,10 @@ Discourse.ShareView = Discourse.View.extend({
|
||||
},
|
||||
|
||||
willDestroyElement: function() {
|
||||
$('html').off('click.discoure-share-link');
|
||||
$('html').off('mousedown.outside-share-link');
|
||||
$('html').off('keydown.share-view');
|
||||
var $html = $('html');
|
||||
$html.off('click.discoure-share-link');
|
||||
$html.off('mousedown.outside-share-link');
|
||||
$html.off('keydown.share-view');
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -7,4 +7,4 @@ I18n.pluralizationRules['cs'] = function (n) {
|
||||
if (n == 1) return "one";
|
||||
if (n >= 2 && n <= 4) return "few";
|
||||
return "other";
|
||||
}
|
||||
};
|
||||
|
@ -7,4 +7,4 @@ I18n.pluralizationRules['ru'] = function (n) {
|
||||
if (n % 10 == 1 && n % 100 != 11) return "one";
|
||||
if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)) return "few";
|
||||
return "many";
|
||||
}
|
||||
};
|
||||
|
@ -22,7 +22,7 @@ module Jobs
|
||||
begin
|
||||
mail_string = mail.pop
|
||||
Email::Receiver.new(mail_string).process
|
||||
rescue Email::Receiver::UserNotSufficientTrustLevelError => e
|
||||
rescue Email::Receiver::UserNotSufficientTrustLevelError
|
||||
# inform the user about the rejection
|
||||
@message = Mail::Message.new(mail_string)
|
||||
clientMessage = RejectionMailer.send_trust_level(@message.from, @message.body)
|
||||
|
Loading…
Reference in New Issue
Block a user