REFACTOR: Migrate more legacy JS to ES6

This commit is contained in:
Robin Ward 2016-06-30 12:26:49 -04:00
parent a546395397
commit 56f07529bb
20 changed files with 168 additions and 152 deletions

View file

@ -179,7 +179,6 @@ window.Discourse = Ember.Application.extend(Discourse.Ajax, {
})
}).create();
Discourse.Markdown = {
whiteListTag: Ember.K,
whiteListIframe: Ember.K

View file

@ -4,6 +4,7 @@ import { linkSeenMentions, fetchUnseenMentions } from 'discourse/lib/link-mentio
import { linkSeenCategoryHashtags, fetchUnseenCategoryHashtags } from 'discourse/lib/link-category-hashtags';
import { fetchUnseenTagHashtags, linkSeenTagHashtags } from 'discourse/lib/link-tag-hashtag';
import { load } from 'pretty-text/oneboxer';
import InputValidation from 'discourse/models/input-validation';
import { tinyAvatar,
displayErrorForUpload,
@ -121,7 +122,7 @@ export default Ember.Component.extend({
}
if (reason) {
return Discourse.InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
return InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
}
},

View file

@ -1,4 +1,5 @@
import { default as computed, on } from 'ember-addons/ember-computed-decorators';
import InputValidation from 'discourse/models/input-validation';
export default Ember.Component.extend({
classNames: ['title-input'],
@ -23,7 +24,7 @@ export default Ember.Component.extend({
}
if (reason) {
return Discourse.InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
return InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt });
}
}
});

View file

@ -1,11 +1,13 @@
import { findAll } from 'discourse/models/login-method';
export default Ember.Component.extend({
elementId: 'login-buttons',
classNameBindings: ['hidden'],
hidden: Em.computed.equal('buttons.length', 0),
hidden: Ember.computed.equal('buttons.length', 0),
buttons: function() {
return Em.get('Discourse.LoginMethod.all');
return findAll(this.siteSettings);
}.property(),
actions: {

View file

@ -5,6 +5,7 @@ import Composer from 'discourse/models/composer';
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
import { relativeAge } from 'discourse/lib/formatter';
import { escapeExpression } from 'discourse/lib/utilities';
import InputValidation from 'discourse/models/input-validation';
function loadDraft(store, opts) {
opts = opts || {};
@ -645,7 +646,7 @@ export default Ember.Controller.extend({
@computed('model.categoryId', 'lastValidatedAt')
categoryValidation(categoryId, lastValidatedAt) {
if( !this.siteSettings.allow_uncategorized_topics && !categoryId) {
return Discourse.InputValidation.create({ failed: true, reason: I18n.t('composer.error.category_missing'), lastShownAt: lastValidatedAt });
return InputValidation.create({ failed: true, reason: I18n.t('composer.error.category_missing'), lastShownAt: lastValidatedAt });
}
},

View file

@ -3,6 +3,7 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
import { setting } from 'discourse/lib/computed';
import { on } from 'ember-addons/ember-computed-decorators';
import { emailValid } from 'discourse/lib/utilities';
import InputValidation from 'discourse/models/input-validation';
export default Ember.Controller.extend(ModalFunctionality, {
needs: ['login'],
@ -87,10 +88,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
// Validate the name.
nameValidation: function() {
if (Discourse.SiteSettings.full_name_required && Ember.isEmpty(this.get('accountName'))) {
return Discourse.InputValidation.create({ failed: true });
return InputValidation.create({ failed: true });
}
return Discourse.InputValidation.create({ok: true});
return InputValidation.create({ok: true});
}.property('accountName'),
// Check the email address
@ -98,7 +99,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
// If blank, fail without a reason
let email;
if (Ember.isEmpty(this.get('accountEmail'))) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true
});
}
@ -106,14 +107,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
email = this.get("accountEmail");
if (this.get('rejectedEmails').contains(email)) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.email.invalid')
});
}
if ((this.get('authOptions.email') === email) && this.get('authOptions.email_valid')) {
return Discourse.InputValidation.create({
return InputValidation.create({
ok: true,
reason: I18n.t('user.email.authenticated', {
provider: this.authProviderDisplayName(this.get('authOptions.auth_provider'))
@ -122,13 +123,13 @@ export default Ember.Controller.extend(ModalFunctionality, {
}
if (emailValid(email)) {
return Discourse.InputValidation.create({
return InputValidation.create({
ok: true,
reason: I18n.t('user.email.ok')
});
}
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.email.invalid')
});
@ -176,15 +177,15 @@ export default Ember.Controller.extend(ModalFunctionality, {
if (this.usernameNeedsToBeValidatedWithEmail()) {
if (this.get('emailValidation.failed')) {
if (this.shouldCheckUsernameMatch()) {
return this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
return this.set('uniqueUsernameValidation', InputValidation.create({
failed: true,
reason: I18n.t('user.username.enter_email')
}));
} else {
return this.set('uniqueUsernameValidation', Discourse.InputValidation.create({ failed: true }));
return this.set('uniqueUsernameValidation', InputValidation.create({ failed: true }));
}
} else if (this.shouldCheckUsernameMatch()) {
this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
this.set('uniqueUsernameValidation', InputValidation.create({
failed: true,
reason: I18n.t('user.username.checking')
}));
@ -197,7 +198,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
this.set('uniqueUsernameValidation', null);
if (this.get('accountUsername') === this.get('prefilledUsername')) {
return Discourse.InputValidation.create({
return InputValidation.create({
ok: true,
reason: I18n.t('user.username.prefilled')
});
@ -205,14 +206,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
// If blank, fail without a reason
if (Ember.isEmpty(this.get('accountUsername'))) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true
});
}
// If too short
if (this.get('accountUsername').length < Discourse.SiteSettings.min_username_length) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.username.too_short')
});
@ -220,7 +221,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
// If too long
if (this.get('accountUsername').length > this.get('maxUsernameLength')) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.username.too_long')
});
@ -228,7 +229,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
this.checkUsernameAvailability();
// Let's check it out asynchronously
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.username.checking')
});
@ -247,23 +248,23 @@ export default Ember.Controller.extend(ModalFunctionality, {
if (result.is_developer) {
_this.set('isDeveloper', true);
}
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
return _this.set('uniqueUsernameValidation', InputValidation.create({
ok: true,
reason: I18n.t('user.username.available')
}));
} else {
if (result.suggestion) {
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
return _this.set('uniqueUsernameValidation', InputValidation.create({
failed: true,
reason: I18n.t('user.username.not_available', result)
}));
} else if (result.errors) {
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
return _this.set('uniqueUsernameValidation', InputValidation.create({
failed: true,
reason: result.errors.join(' ')
}));
} else {
return _this.set('uniqueUsernameValidation', Discourse.InputValidation.create({
return _this.set('uniqueUsernameValidation', InputValidation.create({
failed: true,
reason: I18n.t('user.username.enter_email')
}));
@ -287,47 +288,47 @@ export default Ember.Controller.extend(ModalFunctionality, {
// Validate the password
passwordValidation: function() {
if (!this.get('passwordRequired')) {
return Discourse.InputValidation.create({ ok: true });
return InputValidation.create({ ok: true });
}
// If blank, fail without a reason
const password = this.get("accountPassword");
if (Ember.isEmpty(this.get('accountPassword'))) {
return Discourse.InputValidation.create({ failed: true });
return InputValidation.create({ failed: true });
}
// If too short
const passwordLength = this.get('isDeveloper') ? Discourse.SiteSettings.min_admin_password_length : Discourse.SiteSettings.min_password_length;
if (password.length < passwordLength) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.password.too_short')
});
}
if (this.get('rejectedPasswords').contains(password)) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.password.common')
});
}
if (!Ember.isEmpty(this.get('accountUsername')) && this.get('accountPassword') === this.get('accountUsername')) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.password.same_as_username')
});
}
if (!Ember.isEmpty(this.get('accountEmail')) && this.get('accountPassword') === this.get('accountEmail')) {
return Discourse.InputValidation.create({
return InputValidation.create({
failed: true,
reason: I18n.t('user.password.same_as_email')
});
}
// Looks good!
return Discourse.InputValidation.create({
return InputValidation.create({
ok: true,
reason: I18n.t('user.password.ok')
});

View file

@ -1,6 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import { categoryLinkHTML } from 'discourse/helpers/category-link';
import computed from 'ember-addons/ember-computed-decorators';
import InputValidation from 'discourse/models/input-validation';
export default Ember.Controller.extend(ModalFunctionality, {
needs: ["topic"],
@ -68,14 +69,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
@computed("pinDisabled")
pinInCategoryValidation(pinDisabled) {
if (pinDisabled) {
return Discourse.InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
return InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
}
},
@computed("pinGloballyDisabled")
pinGloballyValidation(pinGloballyDisabled) {
if (pinGloballyDisabled) {
return Discourse.InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
return InputValidation.create({ failed: true, reason: I18n.t("topic.feature_topic.pin_validation") });
}
},

View file

@ -1,6 +1,7 @@
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import showModal from 'discourse/lib/show-modal';
import { setting } from 'discourse/lib/computed';
import { findAll } from 'discourse/models/login-method';
// This is happening outside of the app via popup
const AuthErrors =
@ -22,12 +23,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
this.set('loggedIn', false);
},
/**
Determines whether at least one login button is enabled
**/
// Determines whether at least one login button is enabled
hasAtLeastOneLoginButton: function() {
return Em.get("Discourse.LoginMethod.all").length > 0;
}.property("Discourse.LoginMethod.all.[]"),
return findAll(this.siteSettings).length > 0;
}.property(),
loginButtonText: function() {
return this.get('loggingIn') ? I18n.t('login.logging_in') : I18n.t('login.title');
@ -175,7 +174,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
authMessage: (function() {
if (Ember.isEmpty(this.get('authenticate'))) return "";
const method = Discourse.get('LoginMethod.all').findProperty("name", this.get("authenticate"));
const method = findAll(this.siteSettings).findProperty("name", this.get("authenticate"));
if(method){
return method.get('message');
}

View file

@ -1,4 +1,5 @@
import DiscourseURL from 'discourse/lib/url';
import StaticPage from 'discourse/models/static-page';
const configs = {
"faq": "faq_url",
@ -27,7 +28,7 @@ export default function(page) {
},
model() {
return Discourse.StaticPage.find(page);
return StaticPage.find(page);
},
setupController(controller, model) {

View file

@ -0,0 +1,4 @@
import Model from 'discourse/models/model';
// A trivial model we use to handle input validation
export default Model.extend();

View file

@ -1,11 +0,0 @@
/**
A trivial model we use to handle input validation
@class InputValidation
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.InputValidation = Discourse.Model.extend({});

View file

@ -0,0 +1,71 @@
import computed from 'ember-addons/ember-computed-decorators';
const LoginMethod = Ember.Object.extend({
@computed
title() {
const titleSetting = this.get('titleSetting');
if (!Ember.isEmpty(titleSetting)) {
const result = this.siteSettings[titleSetting];
if (!Ember.isEmpty(result)) { return result; }
}
return this.get("titleOverride") || I18n.t("login." + this.get("name") + ".title");
},
@computed
message() {
return this.get("messageOverride") || I18n.t("login." + this.get("name") + ".message");
}
});
let methods;
let preRegister;
export function findAll(siteSettings) {
if (methods) { return methods; }
methods = [];
[ "google_oauth2", "facebook", "cas", "twitter", "yahoo", "instagram", "github" ].forEach(name => {
if (siteSettings["enable_" + name + "_logins"]) {
const params = { name };
if (name === "google_oauth2") {
params.frameWidth = 850;
params.frameHeight = 500;
} else if (name === "facebook") {
params.frameHeight = 450;
}
params.siteSettings = siteSettings;
methods.pushObject(LoginMethod.create(params));
}
});
if (preRegister){
preRegister.forEach(method => {
const enabledSetting = method.get('enabledSetting');
if (enabledSetting) {
if (siteSettings[enabledSetting]) {
methods.pushObject(method);
}
} else {
methods.pushObject(method);
}
});
preRegister = undefined;
}
return methods;
}
export function register(method) {
method = LoginMethod.create(method);
if (methods) {
methods.pushObject(method);
} else {
preRegister = preRegister || [];
preRegister.push(method);
}
}
export default LoginMethod;

View file

@ -1,74 +0,0 @@
Discourse.LoginMethod = Ember.Object.extend({
title: function() {
var titleSetting = this.get('titleSetting');
if (!Ember.isEmpty(titleSetting)) {
var result = Discourse.SiteSettings[titleSetting];
if (!Ember.isEmpty(result)) { return result; }
}
return this.get("titleOverride") || I18n.t("login." + this.get("name") + ".title");
}.property(),
message: function() {
return this.get("messageOverride") || I18n.t("login." + this.get("name") + ".message");
}.property()
});
// Note, you can add login methods by adding to the list
// just Em.get("Discourse.LoginMethod.all") and then
// pushObject for any new methods
Discourse.LoginMethod.reopenClass({
register: function(method) {
if (this.methods){
this.methods.pushObject(method);
} else {
this.preRegister = this.preRegister || [];
this.preRegister.push(method);
}
},
all: function(){
if (this.methods) { return this.methods; }
var methods = this.methods = Em.A();
[ "google_oauth2",
"facebook",
"cas",
"twitter",
"yahoo",
"instagram",
"github"
].forEach(function(name){
if (Discourse.SiteSettings["enable_" + name + "_logins"]) {
var params = {name: name};
if (name === "google_oauth2") {
params.frameWidth = 850;
params.frameHeight = 500;
} else if (name === "facebook") {
params.frameHeight = 450;
}
methods.pushObject(Discourse.LoginMethod.create(params));
}
});
if (this.preRegister){
this.preRegister.forEach(function(method){
var enabledSetting = method.get('enabledSetting');
if (enabledSetting) {
if (Discourse.SiteSettings[enabledSetting]) {
methods.pushObject(method);
}
} else {
methods.pushObject(method);
}
});
delete this.preRegister;
}
return methods;
}.property()
});

View file

@ -1,8 +1,8 @@
const Model = Ember.Object.extend();
Model.reopenClass({
extractByKey: function(collection, klass) {
var retval = {};
extractByKey(collection, klass) {
const retval = {};
if (Ember.isEmpty(collection)) { return retval; }
collection.forEach(function(item) {

View file

@ -0,0 +1,22 @@
const StaticPage = Ember.Object.extend();
StaticPage.reopenClass({
find(path) {
return new Ember.RSVP.Promise(resolve => {
// Models shouldn't really be doing Ajax request, but this is a huge speed boost if we
// preload content.
const $preloaded = $("noscript[data-path=\"/" + path + "\"]");
if ($preloaded.length) {
let text = $preloaded.text();
text = text.match(/<!-- preload-content: -->((?:.|[\n\r])*)<!-- :preload-content -->/)[1];
resolve(StaticPage.create({path: path, html: text}));
} else {
Discourse.ajax(path + ".html", {dataType: 'html'}).then(function (result) {
resolve(StaticPage.create({path: path, html: result}));
});
}
});
}
});
export default StaticPage;

View file

@ -1,20 +0,0 @@
Discourse.StaticPage = Em.Object.extend();
Discourse.StaticPage.reopenClass({
find: function(path) {
return new Em.RSVP.Promise(function(resolve) {
// Models shouldn't really be doing Ajax request, but this is a huge speed boost if we
// preload content.
var $preloaded = $("noscript[data-path=\"/" + path + "\"]");
if ($preloaded.length) {
var text = $preloaded.text();
text = text.match(/<!-- preload-content: -->((?:.|[\n\r])*)<!-- :preload-content -->/)[1];
resolve(Discourse.StaticPage.create({path: path, html: text}));
} else {
Discourse.ajax(path + ".html", {dataType: 'html'}).then(function (result) {
resolve(Discourse.StaticPage.create({path: path, html: result}));
});
}
});
}
});

View file

@ -4,6 +4,7 @@ import showModal from 'discourse/lib/show-modal';
import OpenComposer from "discourse/mixins/open-composer";
import Category from 'discourse/models/category';
import mobile from 'discourse/lib/mobile';
import { findAll } from 'discourse/models/login-method';
function unlessReadOnly(method, message) {
return function() {
@ -202,7 +203,7 @@ const ApplicationRoute = Discourse.Route.extend(OpenComposer, {
},
_autoLogin(modal, modalClass, notAuto) {
const methods = Em.get('Discourse.LoginMethod.all');
const methods = findAll(this.siteSettings);
if (!this.siteSettings.enable_local_logins && methods.length === 1) {
this.controllerFor('login').send('externalLogin', methods[0]);
} else {

View file

@ -1,9 +1,10 @@
import DiscourseRoute from 'discourse/routes/discourse';
import StaticPage from 'discourse/models/static-page';
export default function(pageName) {
const route = {
model() {
return Discourse.StaticPage.find(pageName);
return StaticPage.find(pageName);
},
renderTemplate() {

View file

@ -234,7 +234,22 @@ class Plugin::Instance
auth_providers.each do |auth|
js << "Discourse.LoginMethod.register(Discourse.LoginMethod.create(#{auth.to_json}));\n"
auth_json = auth.to_json
hash = Digest::SHA1.hexdigest(auth_json)
js << <<JS
define("discourse/initializers/login-method-#{hash}",
["discourse/models/login-method", "exports"],
function(module, __exports__) {
"use strict";
__exports__["default"] = {
name: "login-method-#{hash}",
after: "inject-objects",
initialize: function() {
module.register(#{auth_json});
}
};
});
JS
if auth.glyph
css << ".btn-social.#{auth.name}:before{ content: '#{auth.glyph}'; }\n"

View file

@ -1,4 +1,5 @@
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
import InputValidation from 'discourse/models/input-validation';
export default Ember.Controller.extend({
needs: ['modal'],
@ -131,7 +132,7 @@ export default Ember.Controller.extend({
options = { failed: true, reason: I18n.t("poll.ui_builder.help.options_count") };
}
return Discourse.InputValidation.create(options);
return InputValidation.create(options);
},
_comboboxOptions(start_index, end_index) {