mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 08:57:10 -06:00
Ember 1.12 support
This commit is contained in:
parent
02a968bd27
commit
22844b9e46
@ -20,5 +20,5 @@ vendor/
|
||||
test/javascripts/helpers/
|
||||
test/javascripts/test_helper.js
|
||||
test/javascripts/test_helper.js
|
||||
test/javascripts/fixtures
|
||||
app/assets/javascripts/ember-addons/
|
||||
|
105
.eslintrc
Normal file
105
.eslintrc
Normal file
@ -0,0 +1,105 @@
|
||||
{
|
||||
"env": {
|
||||
"jasmine": true,
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"browser": true,
|
||||
"builtin": true
|
||||
},
|
||||
ecmaVersion: 7,
|
||||
"globals":
|
||||
{"Ember":true,
|
||||
"jQuery":true,
|
||||
"$":true,
|
||||
"RSVP":true,
|
||||
"Discourse":true,
|
||||
"Em":true,
|
||||
"PreloadStore":true,
|
||||
"Handlebars":true,
|
||||
"I18n":true,
|
||||
"bootbox":true,
|
||||
"module":true,
|
||||
"moduleFor":true,
|
||||
"moduleForComponent":true,
|
||||
"Pretender":true,
|
||||
"sandbox":true,
|
||||
"controllerFor":true,
|
||||
"test":true,
|
||||
"ok":true,
|
||||
"not":true,
|
||||
"expect":true,
|
||||
"equal":true,
|
||||
"visit":true,
|
||||
"andThen":true,
|
||||
"click":true,
|
||||
"currentPath":true,
|
||||
"currentRouteName":true,
|
||||
"currentURL":true,
|
||||
"fillIn":true,
|
||||
"keyEvent":true,
|
||||
"triggerEvent":true,
|
||||
"count":true,
|
||||
"exists":true,
|
||||
"visible":true,
|
||||
"invisible":true,
|
||||
"asyncRender":true,
|
||||
"selectDropdown":true,
|
||||
"asyncTestDiscourse":true,
|
||||
"fixture":true,
|
||||
"find":true,
|
||||
"sinon":true,
|
||||
"moment":true,
|
||||
"start":true,
|
||||
"_":true,
|
||||
"alert":true,
|
||||
"containsInstance":true,
|
||||
"deepEqual":true,
|
||||
"notEqual":true,
|
||||
"define":true,
|
||||
"require":true,
|
||||
"requirejs":true,
|
||||
"hasModule":true,
|
||||
"Blob":true,
|
||||
"File":true},
|
||||
"rules": {
|
||||
"block-scoped-var": 2,
|
||||
"dot-notation": 0,
|
||||
"eqeqeq": [
|
||||
2,
|
||||
"allow-null"
|
||||
],
|
||||
"guard-for-in": 2,
|
||||
"no-bitwise": 2,
|
||||
"no-caller": 2,
|
||||
"no-cond-assign": 0,
|
||||
"no-debugger": 2,
|
||||
"no-empty": 0,
|
||||
"no-eval": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-loop-func": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-new": 2,
|
||||
"no-plusplus": 0,
|
||||
"no-proto": 2,
|
||||
"no-script-url": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": 2,
|
||||
"no-undef": 2,
|
||||
"no-unused-vars": 2,
|
||||
"no-with": 2,
|
||||
"semi": [
|
||||
0,
|
||||
"never"
|
||||
],
|
||||
"strict": 0,
|
||||
"valid-typeof": 2,
|
||||
"wrap-iife": [
|
||||
2,
|
||||
"inside"
|
||||
]
|
||||
},
|
||||
"parser": "babel-eslint"
|
||||
}
|
83
.jshintrc
83
.jshintrc
@ -1,83 +0,0 @@
|
||||
{
|
||||
"predef":["Ember",
|
||||
"jQuery",
|
||||
"$",
|
||||
"RSVP",
|
||||
"Discourse",
|
||||
"Em",
|
||||
"PreloadStore",
|
||||
"Handlebars",
|
||||
"I18n",
|
||||
"bootbox",
|
||||
"module",
|
||||
"moduleFor",
|
||||
"moduleForComponent",
|
||||
"Pretender",
|
||||
"sandbox",
|
||||
"controllerFor",
|
||||
"test",
|
||||
"ok",
|
||||
"not",
|
||||
"expect",
|
||||
"equal",
|
||||
"visit",
|
||||
"andThen",
|
||||
"click",
|
||||
"currentPath",
|
||||
"currentRouteName",
|
||||
"currentURL",
|
||||
"fillIn",
|
||||
"keyEvent",
|
||||
"triggerEvent",
|
||||
"count",
|
||||
"exists",
|
||||
"visible",
|
||||
"invisible",
|
||||
"asyncRender",
|
||||
"selectDropdown",
|
||||
"asyncTestDiscourse",
|
||||
"fixture",
|
||||
"find",
|
||||
"sinon",
|
||||
"moment",
|
||||
"start",
|
||||
"_",
|
||||
"alert",
|
||||
"containsInstance",
|
||||
"deepEqual",
|
||||
"notEqual",
|
||||
"define",
|
||||
"require",
|
||||
"requirejs",
|
||||
"hasModule",
|
||||
"Blob",
|
||||
"File"],
|
||||
"node" : false,
|
||||
"browser" : true,
|
||||
"boss" : true,
|
||||
"curly": false,
|
||||
"debug": false,
|
||||
"devel": false,
|
||||
"eqeqeq": true,
|
||||
"evil": true,
|
||||
"forin": false,
|
||||
"immed": false,
|
||||
"laxbreak": false,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"noempty": false,
|
||||
"nonew": false,
|
||||
"nomen": false,
|
||||
"onevar": false,
|
||||
"plusplus": false,
|
||||
"regexp": false,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"sub": true,
|
||||
"strict": false,
|
||||
"white": false,
|
||||
"eqnull": true,
|
||||
"quotmark": false,
|
||||
"lastsemic": true,
|
||||
"esnext": true
|
||||
}
|
@ -46,9 +46,9 @@ GEM
|
||||
multi_json (~> 1.0)
|
||||
aws-sdk-resources (2.0.45)
|
||||
aws-sdk-core (= 2.0.45)
|
||||
babel-source (4.6.6)
|
||||
babel-transpiler (0.6.0)
|
||||
babel-source (>= 4.0, < 5)
|
||||
babel-source (5.8.19)
|
||||
babel-transpiler (0.7.0)
|
||||
babel-source (>= 4.0, < 6)
|
||||
execjs (~> 2.0)
|
||||
barber (0.9.0)
|
||||
ember-source (>= 1.0, < 2)
|
||||
@ -86,7 +86,7 @@ GEM
|
||||
ember-source (>= 1.1.0)
|
||||
jquery-rails (>= 1.0.17)
|
||||
railties (>= 3.1)
|
||||
ember-source (1.11.3.1)
|
||||
ember-source (1.12.1)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.7)
|
||||
excon (0.45.3)
|
||||
|
@ -2,6 +2,7 @@ import BufferedContent from 'discourse/mixins/buffered-content';
|
||||
import ScrollTop from 'discourse/mixins/scroll-top';
|
||||
import SiteSetting from 'admin/models/site-setting';
|
||||
import { propertyNotEqual } from 'discourse/lib/computed';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
const CustomTypes = ['bool', 'enum', 'list', 'url_list', 'host_list'];
|
||||
|
||||
@ -20,19 +21,22 @@ export default Ember.Component.extend(BufferedContent, ScrollTop, {
|
||||
}
|
||||
}.property('buffered.value'),
|
||||
|
||||
typeClass: function() {
|
||||
@computed('partialType')
|
||||
typeClass() {
|
||||
return this.get('partialType').replace("_", "-");
|
||||
}.property('partialType'),
|
||||
},
|
||||
|
||||
enabled: function(key, value) {
|
||||
if (arguments.length > 1) {
|
||||
@computed('buffered.value')
|
||||
enabled: {
|
||||
get() {
|
||||
const bufferedValue = this.get('buffered.value');
|
||||
if (Ember.isEmpty(bufferedValue)) { return false; }
|
||||
return bufferedValue === 'true';
|
||||
},
|
||||
set(key, value) {
|
||||
this.set('buffered.value', value ? 'true' : 'false');
|
||||
}
|
||||
|
||||
const bufferedValue = this.get('buffered.value');
|
||||
if (Ember.isEmpty(bufferedValue)) { return false; }
|
||||
return bufferedValue === 'true';
|
||||
}.property('buffered.value'),
|
||||
},
|
||||
|
||||
settingName: function() {
|
||||
return this.get('setting.setting').replace(/\_/g, ' ');
|
||||
@ -40,7 +44,7 @@ export default Ember.Component.extend(BufferedContent, ScrollTop, {
|
||||
|
||||
partialType: function() {
|
||||
let type = this.get('setting.type');
|
||||
return (CustomTypes.indexOf(type) !== -1) ? type : 'string';
|
||||
return CustomTypes.indexOf(type) !== -1 ? type : 'string';
|
||||
}.property('setting.type'),
|
||||
|
||||
partialName: function() {
|
||||
|
@ -3,7 +3,7 @@ var DiscourseResolver = require('discourse/ember/resolver').default;
|
||||
|
||||
// Allow us to import Ember
|
||||
define('ember', ['exports'], function(__exports__) {
|
||||
__exports__["default"] = Ember;
|
||||
__exports__.default = Ember;
|
||||
});
|
||||
|
||||
window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||
@ -16,7 +16,7 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||
// if it's a non relative URL, return it.
|
||||
if (!/^\/[^\/]/.test(url)) return url;
|
||||
|
||||
var u = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri);
|
||||
var u = Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri;
|
||||
|
||||
if (u[u.length-1] === '/') u = u.substring(0, u.length-1);
|
||||
if (url.indexOf(u) !== -1) return url;
|
||||
@ -66,7 +66,7 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||
// The classes of buttons to show on a post
|
||||
postButtons: function() {
|
||||
return Discourse.SiteSettings.post_menu.split("|").map(function(i) {
|
||||
return (i.replace(/\+/, '').capitalize());
|
||||
return i.replace(/\+/, '').capitalize();
|
||||
});
|
||||
}.property(),
|
||||
|
||||
@ -109,12 +109,26 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||
|
||||
$('noscript').remove();
|
||||
|
||||
// Load any ES6 initializers
|
||||
Ember.keys(requirejs._eak_seen).forEach(function(key) {
|
||||
if (/\/pre\-initializers\//.test(key)) {
|
||||
var module = require(key, null, null, true);
|
||||
if (!module) { throw new Error(key + ' must export an initializer.'); }
|
||||
Discourse.initializer(module.default);
|
||||
}
|
||||
});
|
||||
|
||||
Ember.keys(requirejs._eak_seen).forEach(function(key) {
|
||||
if (/\/initializers\//.test(key)) {
|
||||
var module = require(key, null, null, true);
|
||||
if (!module) { throw new Error(key + ' must export an initializer.'); }
|
||||
Discourse.initializer(module.default);
|
||||
|
||||
var init = module.default;
|
||||
var oldInitialize = init.initialize;
|
||||
init.initialize = function(app) {
|
||||
oldInitialize.call(this, app.container, app);
|
||||
};
|
||||
|
||||
Discourse.instanceInitializer(init);
|
||||
}
|
||||
});
|
||||
|
||||
@ -125,17 +139,22 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||
return desired && Discourse.get("currentAssetVersion") !== desired;
|
||||
}.property("currentAssetVersion", "desiredAssetVersion"),
|
||||
|
||||
assetVersion: function(prop, val) {
|
||||
if(val) {
|
||||
if(this.get("currentAssetVersion")){
|
||||
this.set("desiredAssetVersion", val);
|
||||
} else {
|
||||
this.set("currentAssetVersion", val);
|
||||
}
|
||||
}
|
||||
return this.get("currentAssetVersion");
|
||||
}.property()
|
||||
|
||||
assetVersion: Ember.computed({
|
||||
get: function() {
|
||||
return this.get("currentAssetVersion");
|
||||
},
|
||||
set: function(key, val) {
|
||||
if(val) {
|
||||
if (this.get("currentAssetVersion")) {
|
||||
this.set("desiredAssetVersion", val);
|
||||
} else {
|
||||
this.set("currentAssetVersion", val);
|
||||
}
|
||||
}
|
||||
return this.get("currentAssetVersion");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// TODO: Remove this, it is in for backwards compatibiltiy with plugins
|
||||
@ -159,5 +178,3 @@ proxyDep('URL', function() { return require('discourse/lib/url').default });
|
||||
proxyDep('Quote', function() { return require('discourse/lib/quote').default });
|
||||
proxyDep('debounce', function() { return require('discourse/lib/debounce').default });
|
||||
proxyDep('View', function() { return Ember.View }, "Use `Ember.View` instead");
|
||||
proxyDep('Controller', function() { return Ember.Controller }, "Use `Ember.Controller` instead");
|
||||
proxyDep('ObjectController', function() { return Ember.ObjectController }, "Use `Ember.Controller` instead");
|
||||
|
@ -1,23 +1,31 @@
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['controls'],
|
||||
|
||||
notificationsPermission: function() {
|
||||
@computed
|
||||
notificationsPermission() {
|
||||
if (this.get('isNotSupported')) return '';
|
||||
|
||||
return Notification.permission;
|
||||
}.property(),
|
||||
},
|
||||
|
||||
notificationsDisabled: function(_, value) {
|
||||
if (arguments.length > 1) {
|
||||
localStorage.setItem('notifications-disabled', value);
|
||||
@computed
|
||||
notificationsDisabled: {
|
||||
set(key, value) {
|
||||
if (arguments.length > 1) {
|
||||
localStorage.setItem('notifications-disabled', value);
|
||||
}
|
||||
return localStorage.getItem('notifications-disabled');
|
||||
},
|
||||
get() {
|
||||
return localStorage.getItem('notifications-disabled');
|
||||
}
|
||||
return localStorage.getItem('notifications-disabled');
|
||||
}.property(),
|
||||
},
|
||||
|
||||
|
||||
isNotSupported: function() {
|
||||
return !window['Notification'];
|
||||
}.property(),
|
||||
@computed
|
||||
isNotSupported() {
|
||||
return typeof window.Notification === "undefined";
|
||||
},
|
||||
|
||||
isDefaultPermission: function() {
|
||||
if (this.get('isNotSupported')) return false;
|
||||
|
@ -50,7 +50,7 @@ export default Ember.Controller.extend({
|
||||
// create a marker element
|
||||
const markerElement = document.createElement("span");
|
||||
// containing a single invisible character
|
||||
markerElement.appendChild(document.createTextNode("\u{feff}"));
|
||||
markerElement.appendChild(document.createTextNode("\ufeff"));
|
||||
|
||||
// collapse the range at the beginning/end of the selection
|
||||
range.collapse(!Discourse.Mobile.isMobileDevice);
|
||||
|
@ -1,20 +1,27 @@
|
||||
import searchForTerm from 'discourse/lib/search-for-term';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
let _dontSearch = false;
|
||||
|
||||
export default Em.Controller.extend({
|
||||
typeFilter: null,
|
||||
|
||||
contextType: function(key, value){
|
||||
if(arguments.length > 1) {
|
||||
@computed('searchContext')
|
||||
contextType: {
|
||||
get(searchContext) {
|
||||
if (searchContext) {
|
||||
return Ember.get(searchContext, 'type');
|
||||
}
|
||||
},
|
||||
set(key, value) {
|
||||
// a bit hacky, consider cleaning this up, need to work through all observers though
|
||||
const context = $.extend({}, this.get('searchContext'));
|
||||
context.type = value;
|
||||
this.set('searchContext', context);
|
||||
return this.get('searchContext.type');
|
||||
}
|
||||
return this.get('searchContext.type');
|
||||
}.property('searchContext'),
|
||||
},
|
||||
|
||||
contextChanged: function(){
|
||||
if (this.get('searchContextEnabled')) {
|
||||
|
@ -4,6 +4,7 @@ import { spinnerHTML } from 'discourse/helpers/loading-spinner';
|
||||
import Topic from 'discourse/models/topic';
|
||||
import Quote from 'discourse/lib/quote';
|
||||
import { setting } from 'discourse/lib/computed';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||
multiSelect: false,
|
||||
@ -65,35 +66,53 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||
|
||||
}.observes('model.postStream', 'model.postStream.loadedAllPosts'),
|
||||
|
||||
show_deleted: function(key, value) {
|
||||
const postStream = this.get('model.postStream');
|
||||
if (!postStream) { return; }
|
||||
@computed('model.postStream.summary')
|
||||
show_deleted: {
|
||||
set(key, value) {
|
||||
const postStream = this.get('model.postStream');
|
||||
if (!postStream) { return; }
|
||||
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('show_deleted', value);
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('show_deleted', value);
|
||||
}
|
||||
return postStream.get('show_deleted') ? true : undefined;
|
||||
},
|
||||
get() {
|
||||
return this.get('postStream.show_deleted') ? true : undefined;
|
||||
}
|
||||
return postStream.get('show_deleted') ? true : undefined;
|
||||
}.property('model.postStream.summary'),
|
||||
},
|
||||
|
||||
filter: function(key, value) {
|
||||
const postStream = this.get('model.postStream');
|
||||
if (!postStream) { return; }
|
||||
@computed('model.postStream.summary')
|
||||
filter: {
|
||||
set(key, value) {
|
||||
const postStream = this.get('model.postStream');
|
||||
if (!postStream) { return; }
|
||||
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('summary', value === "summary");
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('summary', value === "summary");
|
||||
}
|
||||
return postStream.get('summary') ? "summary" : undefined;
|
||||
},
|
||||
get() {
|
||||
return this.get('postStream.summary') ? "summary" : undefined;
|
||||
}
|
||||
return postStream.get('summary') ? "summary" : undefined;
|
||||
}.property('model.postStream.summary'),
|
||||
},
|
||||
|
||||
username_filters: function(key, value) {
|
||||
const postStream = this.get('model.postStream');
|
||||
if (!postStream) { return; }
|
||||
@computed('model.postStream.streamFilters.username_filters')
|
||||
username_filters: {
|
||||
set(key, value) {
|
||||
const postStream = this.get('model.postStream');
|
||||
if (!postStream) { return; }
|
||||
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('streamFilters.username_filters', value);
|
||||
if (arguments.length > 1) {
|
||||
postStream.set('streamFilters.username_filters', value);
|
||||
}
|
||||
return postStream.get('streamFilters.username_filters');
|
||||
},
|
||||
get() {
|
||||
return this.get('postStream.streamFilters.username_filters');
|
||||
}
|
||||
return postStream.get('streamFilters.username_filters');
|
||||
}.property('model.postStream.streamFilters.username_filters'),
|
||||
},
|
||||
|
||||
_clearSelected: function() {
|
||||
this.set('selectedPosts', []);
|
||||
@ -489,13 +508,13 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||
|
||||
canMergeTopic: function() {
|
||||
if (!this.get('model.details.can_move_posts')) return false;
|
||||
return (this.get('selectedPostsCount') > 0);
|
||||
return this.get('selectedPostsCount') > 0;
|
||||
}.property('selectedPostsCount'),
|
||||
|
||||
canSplitTopic: function() {
|
||||
if (!this.get('model.details.can_move_posts')) return false;
|
||||
if (this.get('allPostsSelected')) return false;
|
||||
return (this.get('selectedPostsCount') > 0);
|
||||
return this.get('selectedPostsCount') > 0;
|
||||
}.property('selectedPostsCount'),
|
||||
|
||||
canChangeOwner: function() {
|
||||
|
@ -2,6 +2,5 @@ import { applyFlaggedProperties } from 'discourse/controllers/header';
|
||||
|
||||
export default {
|
||||
name: 'apply-flagged-properties',
|
||||
after: 'register-discourse-location',
|
||||
initialize: applyFlaggedProperties
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Append our CSRF token to AJAX requests when necessary.
|
||||
export default {
|
||||
name: "csrf-token",
|
||||
after: 'inject-objects',
|
||||
initialize: function(container) {
|
||||
|
||||
var session = container.lookup('session:main');
|
||||
|
@ -2,7 +2,6 @@ import { showSelector } from "discourse/lib/emoji/emoji-toolbar";
|
||||
|
||||
export default {
|
||||
name: 'enable-emoji',
|
||||
after: 'inject-objects',
|
||||
|
||||
initialize(container) {
|
||||
const siteSettings = container.lookup('site-settings:main');
|
||||
|
@ -1,50 +1,6 @@
|
||||
import Session from 'discourse/models/session';
|
||||
import AppEvents from 'discourse/lib/app-events';
|
||||
import Store from 'discourse/models/store';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
|
||||
function inject() {
|
||||
const app = arguments[0],
|
||||
name = arguments[1],
|
||||
singletonName = Ember.String.underscore(name).replace(/_/, '-') + ':main';
|
||||
|
||||
Array.prototype.slice.call(arguments, 2).forEach(function(dest) {
|
||||
app.inject(dest, name, singletonName);
|
||||
});
|
||||
}
|
||||
|
||||
function injectAll(app, name) {
|
||||
inject(app, name, 'controller', 'component', 'route', 'view', 'model');
|
||||
}
|
||||
// backwards compatibility for plugins that depend on this initializer
|
||||
|
||||
export default {
|
||||
name: "inject-objects",
|
||||
initialize(container, app) {
|
||||
const appEvents = AppEvents.create();
|
||||
app.register('app-events:main', appEvents, { instantiate: false });
|
||||
injectAll(app, 'appEvents');
|
||||
DiscourseURL.appEvents = appEvents;
|
||||
|
||||
app.register('store:main', Store);
|
||||
inject(app, 'store', 'route', 'controller');
|
||||
|
||||
// Inject Discourse.Site to avoid using Discourse.Site.current()
|
||||
const site = Discourse.Site.current();
|
||||
app.register('site:main', site, { instantiate: false });
|
||||
injectAll(app, 'site');
|
||||
|
||||
// Inject Discourse.SiteSettings to avoid using Discourse.SiteSettings globals
|
||||
app.register('site-settings:main', Discourse.SiteSettings, { instantiate: false });
|
||||
injectAll(app, 'siteSettings');
|
||||
|
||||
// Inject Session for transient data
|
||||
app.register('session:main', Session.current(), { instantiate: false });
|
||||
injectAll(app, 'session');
|
||||
|
||||
app.register('current-user:main', Discourse.User.current(), { instantiate: false });
|
||||
inject(app, 'currentUser', 'component', 'route', 'controller');
|
||||
|
||||
app.register('message-bus:main', window.MessageBus, { instantiate: false });
|
||||
inject(app, 'messageBus', 'route', 'controller', 'view', 'component');
|
||||
}
|
||||
initialize: Ember.K
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import PageTracker from 'discourse/lib/page-tracker';
|
||||
|
||||
export default {
|
||||
name: "page-tracking",
|
||||
after: 'register-discourse-location',
|
||||
|
||||
initialize(container) {
|
||||
|
||||
|
@ -1,10 +1,6 @@
|
||||
import DiscourseLocation from 'discourse/lib/discourse-location';
|
||||
// backwards compatibility for plugins that depend on this initializer
|
||||
|
||||
export default {
|
||||
name: "register-discourse-location",
|
||||
after: 'inject-objects',
|
||||
|
||||
initialize: function(container, application) {
|
||||
application.register('location:discourse-location', DiscourseLocation);
|
||||
}
|
||||
initialize: Ember.K
|
||||
};
|
||||
|
@ -4,14 +4,13 @@ import DiscoverySortableController from 'discourse/controllers/discovery-sortabl
|
||||
|
||||
export default {
|
||||
name: 'dynamic-route-builders',
|
||||
after: 'register-discourse-location',
|
||||
|
||||
initialize(container, app) {
|
||||
app.DiscoveryCategoryRoute = buildCategoryRoute('latest');
|
||||
app.DiscoveryParentCategoryRoute = buildCategoryRoute('latest');
|
||||
app.DiscoveryCategoryNoneRoute = buildCategoryRoute('latest', {no_subcategories: true});
|
||||
|
||||
var site = container.lookup('site:main');
|
||||
const site = Discourse.Site.current();
|
||||
site.get('filters').forEach(function(filter) {
|
||||
app["Discovery" + filter.capitalize() + "Controller"] = DiscoverySortableController.extend();
|
||||
app["Discovery" + filter.capitalize() + "Route"] = buildTopicRoute(filter);
|
@ -0,0 +1,53 @@
|
||||
import Session from 'discourse/models/session';
|
||||
import AppEvents from 'discourse/lib/app-events';
|
||||
import Store from 'discourse/models/store';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
import DiscourseLocation from 'discourse/lib/discourse-location';
|
||||
|
||||
function inject() {
|
||||
const app = arguments[0],
|
||||
name = arguments[1],
|
||||
singletonName = Ember.String.underscore(name).replace(/_/, '-') + ':main';
|
||||
|
||||
Array.prototype.slice.call(arguments, 2).forEach(function(dest) {
|
||||
app.inject(dest, name, singletonName);
|
||||
});
|
||||
}
|
||||
|
||||
function injectAll(app, name) {
|
||||
inject(app, name, 'controller', 'component', 'route', 'view', 'model');
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "inject-discourse-objects",
|
||||
initialize(container, app) {
|
||||
const appEvents = AppEvents.create();
|
||||
app.register('app-events:main', appEvents, { instantiate: false });
|
||||
injectAll(app, 'appEvents');
|
||||
DiscourseURL.appEvents = appEvents;
|
||||
|
||||
app.register('store:main', Store);
|
||||
inject(app, 'store', 'route', 'controller');
|
||||
|
||||
// Inject Discourse.Site to avoid using Discourse.Site.current()
|
||||
const site = Discourse.Site.current();
|
||||
app.register('site:main', site, { instantiate: false });
|
||||
injectAll(app, 'site');
|
||||
|
||||
// Inject Discourse.SiteSettings to avoid using Discourse.SiteSettings globals
|
||||
app.register('site-settings:main', Discourse.SiteSettings, { instantiate: false });
|
||||
injectAll(app, 'siteSettings');
|
||||
|
||||
// Inject Session for transient data
|
||||
app.register('session:main', Session.current(), { instantiate: false });
|
||||
injectAll(app, 'session');
|
||||
|
||||
app.register('current-user:main', Discourse.User.current(), { instantiate: false });
|
||||
inject(app, 'currentUser', 'component', 'route', 'controller');
|
||||
|
||||
app.register('message-bus:main', window.MessageBus, { instantiate: false });
|
||||
inject(app, 'messageBus', 'route', 'controller', 'view', 'component');
|
||||
|
||||
app.register('location:discourse-location', DiscourseLocation);
|
||||
}
|
||||
};
|
@ -2,7 +2,7 @@ import { mapRoutes } from 'discourse/router';
|
||||
|
||||
export default {
|
||||
name: "map-routes",
|
||||
after: 'inject-objects',
|
||||
after: 'inject-discourse-objects',
|
||||
|
||||
initialize(container, app) {
|
||||
app.register('router:main', mapRoutes());
|
@ -1,3 +1,3 @@
|
||||
export default Discourse.View.extend({
|
||||
export default Ember.View.extend({
|
||||
classNames: ["topic-unsubscribe"]
|
||||
});
|
||||
|
22
app/assets/javascripts/ember-addons/decorator-alias.js.es6
Normal file
22
app/assets/javascripts/ember-addons/decorator-alias.js.es6
Normal file
@ -0,0 +1,22 @@
|
||||
import extractValue from './utils/extract-value';
|
||||
|
||||
export default function decoratorAlias(fn, errorMessage) {
|
||||
return function(...params) {
|
||||
// determine if user called as @computed('blah', 'blah') or @computed
|
||||
if (params.length === 0) {
|
||||
throw new Error(errorMessage);
|
||||
} else {
|
||||
return function(target, key, desc) {
|
||||
return {
|
||||
enumerable: desc.enumerable,
|
||||
configurable: desc.configurable,
|
||||
writable: desc.writable,
|
||||
initializer: function() {
|
||||
var value = extractValue(desc);
|
||||
return fn.apply(null, params.concat(value));
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
import handleDescriptor from './utils/handle-descriptor';
|
||||
import isDescriptor from './utils/is-descriptor';
|
||||
import extractValue from './utils/extract-value';
|
||||
|
||||
export default function computedDecorator(...params) {
|
||||
// determine if user called as @computed('blah', 'blah') or @computed
|
||||
if (isDescriptor(params[params.length - 1])) {
|
||||
return handleDescriptor(...arguments);
|
||||
} else {
|
||||
return function(/* target, key, desc */) {
|
||||
return handleDescriptor(...arguments, params);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function readOnly(target, name, desc) {
|
||||
return {
|
||||
writable: false,
|
||||
enumerable: desc.enumerable,
|
||||
configurable: desc.configurable,
|
||||
initializer: function() {
|
||||
var value = extractValue(desc);
|
||||
return value.readOnly();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
import decoratorAlias from './decorator-alias';
|
||||
|
||||
export var on = decoratorAlias(Ember.on, 'Can not `on` without event names');
|
||||
export var observes = decoratorAlias(Ember.observer, 'Can not `observe` without property names');
|
||||
|
||||
import macroAlias from './macro-alias';
|
||||
|
||||
export var alias = macroAlias(Ember.computed.alias);
|
||||
export var and = macroAlias(Ember.computed.and);
|
||||
export var bool = macroAlias(Ember.computed.bool);
|
||||
export var collect = macroAlias(Ember.computed.collect);
|
||||
export var empty = macroAlias(Ember.computed.empty);
|
||||
export var equal = macroAlias(Ember.computed.equal);
|
||||
export var filter = macroAlias(Ember.computed.filter);
|
||||
export var filterBy = macroAlias(Ember.computed.filterBy);
|
||||
export var gt = macroAlias(Ember.computed.gt);
|
||||
export var gte = macroAlias(Ember.computed.gte);
|
||||
export var lt = macroAlias(Ember.computed.lt);
|
||||
export var lte = macroAlias(Ember.computed.lte);
|
||||
export var map = macroAlias(Ember.computed.map);
|
||||
export var mapBy = macroAlias(Ember.computed.mapBy);
|
||||
export var match = macroAlias(Ember.computed.match);
|
||||
export var max = macroAlias(Ember.computed.max);
|
||||
export var min = macroAlias(Ember.computed.min);
|
||||
export var none = macroAlias(Ember.computed.none);
|
||||
export var not = macroAlias(Ember.computed.not);
|
||||
export var notEmpty = macroAlias(Ember.computed.notEmpty);
|
||||
export var oneWay = macroAlias(Ember.computed.oneWay);
|
||||
export var or = macroAlias(Ember.computed.or);
|
||||
export var readOnly = macroAlias(Ember.computed.readOnly);
|
||||
export var reads = macroAlias(Ember.computed.reads);
|
||||
export var setDiff = macroAlias(Ember.computed.setDiff);
|
||||
export var sort = macroAlias(Ember.computed.sort);
|
||||
export var sum = macroAlias(Ember.computed.sum);
|
||||
export var union = macroAlias(Ember.computed.union);
|
||||
export var uniq = macroAlias(Ember.computed.uniq);
|
24
app/assets/javascripts/ember-addons/macro-alias.js.es6
Normal file
24
app/assets/javascripts/ember-addons/macro-alias.js.es6
Normal file
@ -0,0 +1,24 @@
|
||||
import isDescriptor from './utils/is-descriptor';
|
||||
|
||||
function handleDescriptor(target, property, desc, fn, params = []) {
|
||||
return {
|
||||
enumerable: desc.enumerable,
|
||||
configurable: desc.configurable,
|
||||
writable: desc.writable,
|
||||
initializer: function() {
|
||||
return fn(...params);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function macroAlias(fn) {
|
||||
return function(...params) {
|
||||
if (isDescriptor(params[params.length - 1])) {
|
||||
return handleDescriptor(...params, fn);
|
||||
} else {
|
||||
return function(target, property, desc) {
|
||||
return handleDescriptor(target, property, desc, fn, params);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export default function extractValue(desc) {
|
||||
return desc.value ||
|
||||
(typeof desc.initializer === 'function' && desc.initializer());
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
import Ember from 'ember';
|
||||
import extractValue from './extract-value';
|
||||
|
||||
const { computed, get } = Ember;
|
||||
|
||||
export default function handleDescriptor(target, key, desc, params = []) {
|
||||
return {
|
||||
enumerable: desc.enumerable,
|
||||
configurable: desc.configurable,
|
||||
writeable: desc.writeable,
|
||||
initializer: function() {
|
||||
let computedDescriptor;
|
||||
|
||||
if (desc.writable) {
|
||||
var val = extractValue(desc);
|
||||
if (typeof val === 'object') {
|
||||
let value = { };
|
||||
if (val.get) { value.get = callUserSuppliedGet(params, val.get); }
|
||||
if (val.set) { value.set = callUserSuppliedSet(params, val.set); }
|
||||
computedDescriptor = value;
|
||||
} else {
|
||||
computedDescriptor = callUserSuppliedGet(params, val);
|
||||
}
|
||||
} else {
|
||||
throw new Error('ember-computed-decorators does not support using getters and setters');
|
||||
}
|
||||
|
||||
return computed.apply(null, params.concat(computedDescriptor));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function niceAttr(attr) {
|
||||
const parts = attr.split('.');
|
||||
let i;
|
||||
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
if (parts[i] === '@each' ||
|
||||
parts[i] === '[]' ||
|
||||
parts[i].indexOf('{') !== -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return parts.slice(0, i).join('.');
|
||||
}
|
||||
|
||||
function callUserSuppliedGet(params, func) {
|
||||
params = params.map(niceAttr);
|
||||
return function() {
|
||||
let paramValues = params.map(p => get(this, p));
|
||||
|
||||
return func.apply(this, paramValues);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function callUserSuppliedSet(params, func) {
|
||||
params = params.map(niceAttr);
|
||||
return function(key, value) {
|
||||
let paramValues = params.map(p => get(this, p));
|
||||
paramValues.unshift(value);
|
||||
|
||||
return func.apply(this, paramValues);
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
export default function isDescriptor(item) {
|
||||
return item &&
|
||||
typeof item === 'object' &&
|
||||
'writable' in item &&
|
||||
'enumerable' in item &&
|
||||
'configurable' in item;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<%
|
||||
if Rails.env.development? || Rails.env.test?
|
||||
require_asset ("ember-template-compiler.js")
|
||||
require_asset ("ember.custom.debug.js")
|
||||
require_asset ("ember.debug.js")
|
||||
else
|
||||
require_asset ("ember-template-compiler.js")
|
||||
require_asset ("ember.prod.js")
|
||||
|
@ -5,6 +5,10 @@
|
||||
//= require ./pagedown_custom.js
|
||||
|
||||
// Stuff we need to load first
|
||||
//= require_tree ./ember-addons/utils
|
||||
//= require ./ember-addons/decorator-alias
|
||||
//= require ./ember-addons/macro-alias
|
||||
//= require ./ember-addons/ember-computed-decorators
|
||||
//= require ./discourse/lib/load-script
|
||||
//= require ./discourse/lib/notification-levels
|
||||
//= require ./discourse/lib/app-events
|
||||
@ -94,4 +98,5 @@
|
||||
//= require_tree ./discourse/helpers
|
||||
//= require_tree ./discourse/templates
|
||||
//= require_tree ./discourse/routes
|
||||
//= require_tree ./discourse/pre-initializers
|
||||
//= require_tree ./discourse/initializers
|
||||
|
@ -26,8 +26,8 @@
|
||||
});
|
||||
|
||||
<% if Rails.env.development? || Rails.env.test? %>
|
||||
Ember.ENV.RAISE_ON_DEPRECATION = true
|
||||
Ember.LOG_STACKTRACE_ON_DEPRECATION = true
|
||||
//Ember.ENV.RAISE_ON_DEPRECATION = true
|
||||
//Ember.LOG_STACKTRACE_ON_DEPRECATION = true
|
||||
<% end %>
|
||||
|
||||
</script>
|
||||
|
@ -31,7 +31,7 @@ class DiscourseIIFE < Sprockets::Processor
|
||||
req_path = path.sub(Rails.root.to_s, '')
|
||||
.sub("/app/assets/javascripts", "")
|
||||
.sub("/test/javascripts", "")
|
||||
res << "\nwindow.__jshintSrc = window.__jshintSrc || {}; window.__jshintSrc['/assets#{req_path}'] = #{data.to_json};\n"
|
||||
res << "\nwindow.__eslintSrc = window.__eslintSrc || {}; window.__eslintSrc['/assets#{req_path}'] = #{data.to_json};\n"
|
||||
end
|
||||
|
||||
res
|
||||
|
@ -83,8 +83,6 @@ module Tilt
|
||||
@output = klass.v8.eval(generate_source(scope))
|
||||
end
|
||||
|
||||
source = @output.dup
|
||||
|
||||
# For backwards compatibility with plugins, for now export the Global format too.
|
||||
# We should eventually have an upgrade system for plugins to use ES6 or some other
|
||||
# resolve based API.
|
||||
@ -129,7 +127,7 @@ module Tilt
|
||||
end
|
||||
req_path = "/assets/#{scope.logical_path}.#{extension}"
|
||||
|
||||
@output << "\nwindow.__jshintSrc = window.__jshintSrc || {}; window.__jshintSrc['#{req_path}'] = #{data.to_json};\n"
|
||||
@output << "\nwindow.__eslintSrc = window.__eslintSrc || {}; window.__eslintSrc['#{req_path}'] = #{data.to_json};\n"
|
||||
end
|
||||
|
||||
@output
|
||||
@ -139,7 +137,7 @@ module Tilt
|
||||
|
||||
def generate_source(scope)
|
||||
js_source = ::JSON.generate(data, quirks_mode: true)
|
||||
js_source = "babel.transform(#{js_source}, {ast: false, whitelist: ['es6.constants', 'es6.properties.shorthand', 'es6.arrowFunctions', 'es6.blockScoping', 'es6.destructuring', 'es6.templateLiterals', 'es6.regex.unicode']})['code']"
|
||||
js_source = "babel.transform(#{js_source}, {ast: false, whitelist: ['es6.constants', 'es6.properties.shorthand', 'es6.arrowFunctions', 'es6.blockScoping', 'es6.destructuring', 'es6.spread', 'es6.parameters', 'es6.templateLiterals', 'es6.regex.unicode', 'es7.decorators']})['code']"
|
||||
"new module.exports.Compiler(#{js_source}, '#{module_name(scope.root_path, scope.logical_path)}', #{compiler_options}).#{compiler_method}()"
|
||||
end
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
module("JSHint");
|
||||
|
||||
<%= "const JSHINT_OPTS = #{File.read(File.join(Rails.root, '.jshintrc'))};" %>
|
||||
|
||||
var qHint = function(name, sourceFile) {
|
||||
return asyncTestDiscourse(name, function() {
|
||||
if (typeof window.__jshintSrc !== "undefined") {
|
||||
var src = window.__jshintSrc[sourceFile];
|
||||
if (src) {
|
||||
start();
|
||||
qHint.validateFile(src, JSHINT_OPTS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
qHint.validateFile = function (source, options, globals) {
|
||||
var i, len, err;
|
||||
|
||||
source = source.replace(/^[^]*\/\/ IIFE Wrapped Content Begins:\n\n/m, "");
|
||||
source = source.replace(/\n\n\/\/ IIFE Wrapped Content Ends[^]*$/m, "");
|
||||
|
||||
if (JSHINT(source, options, globals)) {
|
||||
ok(true);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, len = JSHINT.errors.length; i < len; i++) {
|
||||
err = JSHINT.errors[i];
|
||||
if (!err) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ok(false, err.reason +
|
||||
" on line " + err.line +
|
||||
", character " + err.character);
|
||||
}
|
||||
};
|
||||
|
||||
var XMLHttpFactories = [
|
||||
function () { return new XMLHttpRequest(); },
|
||||
function () { return new ActiveXObject("Msxml2.XMLHTTP"); },
|
||||
function () { return new ActiveXObject("Msxml3.XMLHTTP"); },
|
||||
function () { return new ActiveXObject("Microsoft.XMLHTTP"); }
|
||||
];
|
||||
|
||||
function createXMLHTTPObject() {
|
||||
for (var i = 0; i < XMLHttpFactories.length; i++) {
|
||||
try {
|
||||
return XMLHttpFactories[i]();
|
||||
} catch (e) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// modified version of XHR script by PPK
|
||||
// http://www.quirksmode.org/js/xmlhttp.html
|
||||
// attached to qHint to allow substitution / mocking
|
||||
qHint.sendRequest = function (url, callback) {
|
||||
var req = createXMLHTTPObject();
|
||||
if (!req) {
|
||||
return;
|
||||
}
|
||||
|
||||
var method = "GET";
|
||||
req.open(method,url + "?" + (new Date().getTime()),true);
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState != 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(req);
|
||||
};
|
||||
|
||||
if (req.readyState == 4) {
|
||||
return;
|
||||
}
|
||||
req.send();
|
||||
};
|
||||
|
||||
<%
|
||||
TO_IGNORE = File.read("#{Rails.root}/.jshintignore").split("\n")
|
||||
|
||||
def jshint(dir, remove)
|
||||
result = ""
|
||||
|
||||
Dir.glob(dir).each do |f|
|
||||
filename = f.sub("#{Rails.root}/#{remove}", "")
|
||||
|
||||
ok = true
|
||||
TO_IGNORE.each do |ig|
|
||||
ok = false unless (filename.index(ig.sub(remove, '')).nil?)
|
||||
end
|
||||
|
||||
depend_on filename
|
||||
result << "qHint('#{filename}', '/assets/#{filename}', JSHINT_OPTS);\n" if ok
|
||||
|
||||
end
|
||||
result
|
||||
end
|
||||
%>
|
||||
|
||||
<%= jshint("#{Rails.root}/test/**/*.js", "test/javascripts/") %>
|
||||
<%= jshint("#{Rails.root}/app/assets/javascripts/**/*.js", "app/assets/javascripts/") %>
|
||||
<%= jshint("#{Rails.root}/app/assets/javascripts/**/*.es6", "app/assets/javascripts/") %>
|
||||
|
@ -75,7 +75,7 @@ test("removes the href and put it as a data attribute", function() {
|
||||
ok(DiscourseURL.redirectTo.calledOnce);
|
||||
});
|
||||
|
||||
asyncTest("restores the href after a while", function() {
|
||||
asyncTestDiscourse("restores the href after a while", function() {
|
||||
expect(1);
|
||||
|
||||
track(generateClickEventOn('a'));
|
||||
|
@ -1,4 +1,3 @@
|
||||
/*jshint maxlen:250 */
|
||||
/*global document, sinon, QUnit, Logster */
|
||||
|
||||
//= require env
|
||||
@ -12,7 +11,7 @@
|
||||
//= require jquery.debug
|
||||
//= require jquery.ui.widget
|
||||
//= require handlebars
|
||||
//= require ember.custom.debug
|
||||
//= require ember.debug
|
||||
//= require message-bus
|
||||
//= require ember-qunit
|
||||
//= require fake_xml_http_request
|
||||
@ -36,7 +35,6 @@
|
||||
|
||||
//= require sinon-1.7.1
|
||||
//= require sinon-qunit-1.0.0
|
||||
//= require jshint
|
||||
|
||||
//= require helpers/qunit-helpers
|
||||
//= require helpers/assertions
|
||||
|
9924
vendor/assets/javascripts/ember-template-compiler.js
vendored
9924
vendor/assets/javascripts/ember-template-compiler.js
vendored
File diff suppressed because it is too large
Load Diff
49400
vendor/assets/javascripts/ember.custom.debug.js
vendored
49400
vendor/assets/javascripts/ember.custom.debug.js
vendored
File diff suppressed because it is too large
Load Diff
12047
vendor/assets/javascripts/jshint.js
vendored
12047
vendor/assets/javascripts/jshint.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user