Many fixes for Ember 1.9.0

This commit is contained in:
Robin Ward 2014-12-10 11:34:00 -05:00
parent 61101736cb
commit 5659b93c71
29 changed files with 9429 additions and 8052 deletions

View File

@ -104,8 +104,8 @@ end
gem 'onebox' gem 'onebox'
gem 'ember-rails' gem 'ember-rails'
gem 'ember-source', '1.6.0.beta.2' gem 'ember-source', '1.9.0.beta.4'
gem 'handlebars-source', '1.3.0' gem 'handlebars-source', '2.0.0'
gem 'barber' gem 'barber'
gem 'message_bus' gem 'message_bus'

View File

@ -77,8 +77,8 @@ GEM
handlebars-source handlebars-source
jquery-rails (>= 1.0.17) jquery-rails (>= 1.0.17)
railties (>= 3.1) railties (>= 3.1)
ember-source (1.6.0.beta.2) ember-source (1.9.0.beta.4)
handlebars-source (~> 1.0) handlebars-source (~> 2.0)
erubis (2.7.0) erubis (2.7.0)
eventmachine (1.0.3) eventmachine (1.0.3)
excon (0.39.6) excon (0.39.6)
@ -129,7 +129,7 @@ GEM
given_core (3.5.4) given_core (3.5.4)
sorcerer (>= 0.3.7) sorcerer (>= 0.3.7)
guess_html_encoding (0.0.9) guess_html_encoding (0.0.9)
handlebars-source (1.3.0) handlebars-source (2.0.0)
hashie (3.3.1) hashie (3.3.1)
highline (1.6.21) highline (1.6.21)
hike (1.2.3) hike (1.2.3)
@ -414,7 +414,7 @@ DEPENDENCIES
certified certified
email_reply_parser email_reply_parser
ember-rails ember-rails
ember-source (= 1.6.0.beta.2) ember-source (= 1.9.0.beta.4)
eventmachine eventmachine
fabrication (= 2.9.8) fabrication (= 2.9.8)
fakeweb (~> 1.3.0) fakeweb (~> 1.3.0)
@ -426,7 +426,7 @@ DEPENDENCIES
fog (= 1.22.1) fog (= 1.22.1)
foreman foreman
gctools gctools
handlebars-source (= 1.3.0) handlebars-source (= 2.0.0)
highline highline
hiredis hiredis
htmlentities htmlentities

View File

@ -1,11 +1,3 @@
/**
This view is used for rendering a basic list of topics.
@class BasicTopicListComponent
@extends Discourse.View
@namespace Discourse
@module Discourse
**/
export default Ember.Component.extend({ export default Ember.Component.extend({
loading: Ember.computed.not('loaded'), loading: Ember.computed.not('loaded'),

View File

@ -4,9 +4,9 @@ var classify = Ember.String.classify;
var get = Ember.get; var get = Ember.get;
var LOADING_WHITELIST = ['badges', 'userActivity', 'userPrivateMessages', 'admin', 'adminFlags', var LOADING_WHITELIST = ['badges', 'userActivity', 'userPrivateMessages', 'admin', 'adminFlags',
'user', 'preferences', 'adminEmail', 'adminUsersList'], 'user', 'preferences', 'adminEmail', 'adminUsersList'];
_dummyRoute, var _dummyRoute;
_loadingView; var _loadingView;
function loadingResolver(cb) { function loadingResolver(cb) {
return function(parsedName) { return function(parsedName) {
@ -150,8 +150,7 @@ export default Ember.DefaultResolver.extend({
// Try to find a template with slash instead of first underscore, e.g. foo_bar_baz => foo/bar_baz // Try to find a template with slash instead of first underscore, e.g. foo_bar_baz => foo/bar_baz
findSlashedTemplate: function(parsedName) { findSlashedTemplate: function(parsedName) {
var decamelized = parsedName.fullNameWithoutType.decamelize(); var decamelized = parsedName.fullNameWithoutType.decamelize();
var slashed = decamelized.replace("_", "/"); return Ember.TEMPLATES[decamelized.replace("_", "/")] || Ember.TEMPLATES[decamelized.replace('.', '/')];
return Ember.TEMPLATES[slashed];
}, },
// Try to find a template within a special admin namespace, e.g. adminEmail => admin/templates/email // Try to find a template within a special admin namespace, e.g. adminEmail => admin/templates/email

View File

@ -1,5 +1,8 @@
var safe = Handlebars.SafeString; var safe = Handlebars.SafeString;
// TODO: Remove me when ES6ified
var registerUnbound = require('discourse/helpers/register-unbound', null, null, true).default;
/** /**
Bound avatar helper. Bound avatar helper.
@ -56,25 +59,18 @@ Handlebars.registerHelper('age-with-tooltip', function(property, options) {
return new safe(Discourse.Formatter.autoUpdatingRelativeAge(dt, {title: true})); return new safe(Discourse.Formatter.autoUpdatingRelativeAge(dt, {title: true}));
}); });
/** registerUnbound('number', function(orig, params) {
Display logic for numbers. orig = parseInt(orig, 10);
@method number
@for Handlebars
**/
Handlebars.registerHelper('number', function(property, options) {
var orig = parseInt(Ember.Handlebars.get(this, property, options), 10);
if (isNaN(orig)) { orig = 0; } if (isNaN(orig)) { orig = 0; }
var title = orig; var title = orig;
if (options.hash.numberKey) { if (params.numberKey) {
title = I18n.t(options.hash.numberKey, { number: orig }); title = I18n.t(params.numberKey, { number: orig });
} }
var classNames = 'number'; var classNames = 'number';
if (options.hash['class']) { if (params['class']) {
classNames += ' ' + Ember.Handlebars.get(this, options.hash['class'], options); classNames += ' ' + params['class'];
} }
var result = "<span class='" + classNames + "'"; var result = "<span class='" + classNames + "'";

View File

@ -1,5 +1,4 @@
import { categoryLinkHTML } from 'discourse/lib/html-builder'; import { categoryLinkHTML } from 'discourse/lib/html-builder';
import registerUnbound from 'discourse/helpers/register-unbound';
Handlebars.registerHelper('category-link', function(property, options) { registerUnbound('category-link', categoryLinkHTML);
return categoryLinkHTML(Ember.Handlebars.get(this, property, options), options);
});

View File

@ -2,8 +2,7 @@ Handlebars.registerHelper('custom-html', function(name, contextString, options)
var html = Discourse.HTML.getCustomHTML(name); var html = Discourse.HTML.getCustomHTML(name);
if (html) { return html; } if (html) { return html; }
var container = (options || contextString).data.keywords.controller.container; var container = (options || contextString).data.view.container;
if (container.lookup('template:' + name)) { if (container.lookup('template:' + name)) {
return Ember.Handlebars.helpers.partial.apply(this, arguments); return Ember.Handlebars.helpers.partial.apply(this, arguments);
} }

View File

@ -1,27 +1,24 @@
import registerUnbound from 'discourse/helpers/register-unbound';
/** /**
Display logic for dates. It is unbound in Ember but will use jQuery to Display logic for dates. It is unbound in Ember but will use jQuery to
update the dates on a regular interval. update the dates on a regular interval.
**/ **/
Handlebars.registerHelper('format-date', function(property, options) { registerUnbound('format-date', function(val, params) {
var leaveAgo, format = 'medium', title = true; var leaveAgo,
var hash = property.hash || (options && options.hash); format = 'medium',
title = true;
if (hash) { if (params.leaveAgo) {
if (hash.leaveAgo) { leaveAgo = params.leaveAgo === "true";
leaveAgo = hash.leaveAgo === "true";
} }
if (hash.path) { if (params.format) {
property = hash.path; format = params.format;
} }
if (hash.format) { if (params.noTitle) {
format = hash.format;
}
if (hash.noTitle) {
title = false; title = false;
} }
}
var val = Ember.Handlebars.get(this, property, options);
if (val) { if (val) {
var date = new Date(val); var date = new Date(val);
return new Handlebars.SafeString(Discourse.Formatter.autoUpdatingRelativeAge(date, {format: format, title: title, leaveAgo: leaveAgo})); return new Handlebars.SafeString(Discourse.Formatter.autoUpdatingRelativeAge(date, {format: format, title: title, leaveAgo: leaveAgo}));

View File

@ -1,3 +1,6 @@
// TODO: Remove me when ES6ified
var registerUnbound = require('discourse/helpers/register-unbound', null, null, true).default;
/** /**
We always prefix with "js." to select exactly what we want passed We always prefix with "js." to select exactly what we want passed
through to the front end. through to the front end.
@ -17,26 +20,8 @@ I18n.toHumanSize = function(number, options) {
return oldI18ntoHumanSize.apply(this, [number, options]); return oldI18ntoHumanSize.apply(this, [number, options]);
}; };
/** registerUnbound('i18n', function(key, params) {
Look up a translation for an i18n key in our dictionary. return I18n.t(key, params);
@method i18n
@for Handlebars
**/
Handlebars.registerHelper('i18n', function(property, options) {
// Resolve any properties
var params = options.hash,
self = this;
if (options.types[0] !== "STRING") {
Em.warn("Using the `{{i18n}}` helper without quotes is deprecated.");
}
_.each(params, function(value, key) {
params[key] = Em.Handlebars.get(self, value, options);
});
return I18n.t(property, params);
}); });
/** /**

View File

@ -3,6 +3,9 @@ Handlebars.registerHelper('raw', function(property, options) {
template = Discourse.__container__.lookup('template:' + templateName), template = Discourse.__container__.lookup('template:' + templateName),
params = options.hash; params = options.hash;
// {{raw}} helper is broken!
return;
if (!template) { if (!template) {
Ember.warn('Could not find raw template: ' + templateName); Ember.warn('Could not find raw template: ' + templateName);
return; return;
@ -11,7 +14,7 @@ Handlebars.registerHelper('raw', function(property, options) {
if (params) { if (params) {
for (var prop in params) { for (var prop in params) {
if (options.hashTypes[prop] === "ID") { if (options.hashTypes[prop] === "ID") {
params[prop] = Ember.Handlebars.get(this, params[prop], options); params[prop] = Ember.get(this, params[prop], options);
} }
} }
} }

View File

@ -0,0 +1,26 @@
function registerUnbound(name, fn) {
Handlebars.registerHelper(name, function(property, options) {
if (options.types[0] === "ID") {
property = options.data.view.getStream(property).value();
}
var params = {},
hash = options.hash;
if (hash) {
Ember.keys(options.hash).forEach(function(k) {
var type = options.hashTypes[k];
if (type === "STRING") {
params[k] = hash[k];
} else if (type === "ID") {
params[k] = options.data.view.getStream(hash[k]).value();
}
});
}
return fn(property, params);
});
}
export default registerUnbound;

View File

@ -1,6 +1,6 @@
Handlebars.registerHelper('topic-link', function(property, options) { import registerUnbound from 'discourse/helpers/register-unbound';
var topic = Ember.Handlebars.get(this, property, options),
title = topic.get('fancy_title');
registerUnbound('topic-link', function(topic) {
var title = topic.get('fancy_title');
return new Handlebars.SafeString("<a href='" + topic.get('lastUnreadUrl') + "' class='title'>" + title + "</a>"); return new Handlebars.SafeString("<a href='" + topic.get('lastUnreadUrl') + "' class='title'>" + title + "</a>");
}); });

View File

@ -1,3 +1,5 @@
import registerUnbound from 'discourse/helpers/register-unbound';
export function renderAvatar(user, options) { export function renderAvatar(user, options) {
options = options || {}; options = options || {};
@ -39,9 +41,6 @@ export function renderAvatar(user, options) {
} }
} }
Handlebars.registerHelper('avatar', function(user, options) { registerUnbound('avatar', function(user, params) {
if (typeof user === 'string') { return new Handlebars.SafeString(renderAvatar.call(this, user, params));
user = Ember.Handlebars.get(this, user, options);
}
return new Handlebars.SafeString(renderAvatar.call(this, user, options.hash));
}); });

View File

@ -17,34 +17,34 @@
</thead> </thead>
<tbody> <tbody>
{{#each topics}} {{#each t in topics}}
<tr {{bind-attr class="archived"}}> <tr {{bind-attr class="t.archived"}}>
<td class='main-link'> <td class='main-link'>
{{topic-status topic=this}} {{topic-status topic=t}}
<a class='title' href="{{unbound lastUnreadUrl}}">{{{unbound fancy_title}}}</a> <a class='title' href="{{unbound t.lastUnreadUrl}}">{{{unbound t.fancy_title}}}</a>
{{topic-post-badges unread=unread {{topic-post-badges unread=t.unread
newPosts=new_posts newPosts=t.new_posts
unseen=unseen unseen=t.unseen
url=lastUnreadUrl}} url=t.lastUnreadUrl}}
</td> </td>
{{raw "list/category-column" hideCategory=controller.hideCategory category=category}} {{raw "list/category-column" hideCategory=controller.hideCategory category=t.category}}
{{posts-count-column topic=this class="num" action="clickedPosts"}} {{posts-count-column topic=t class="num" action="clickedPosts"}}
{{#if controller.showParticipants}} {{#if controller.showParticipants}}
<td class='participants'> <td class='participants'>
{{#each participants}} {{#each p in t.participants}}
<a href="{{unbound user.path}}" data-user-card="{{unbound user.username}}" class="{{unbound extras}}">{{avatar this usernamePath="user.username" imageSize="small"}}</a> <a href="{{unbound p.user.path}}" data-user-card="{{unbound p.user.username}}" class="{{unbound p.extras}}">{{avatar p usernamePath="user.username" imageSize="small"}}</a>
{{/each}} {{/each}}
</td> </td>
{{/if}} {{/if}}
<td {{bind-attr class=":num :views viewsHeat"}}> <td {{bind-attr class=":num :views t.viewsHeat"}}>
{{number views numberKey="views_long"}} {{number t.views numberKey="views_long"}}
</td> </td>
{{raw "list/activity-column" topic=this class="num" tagName="td"}} {{raw "list/activity-column" topic=t class="num" tagName="td"}}
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>

View File

@ -64,7 +64,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{each topics itemController="topic-list-item" itemView="topic-list-item"}} {{each content in topics itemController="topic-list-item" itemView="topic-list-item"}}
</tbody> </tbody>
</table> </table>
{{/if}} {{/if}}

View File

@ -3,7 +3,7 @@
<div class='item'> <div class='item'>
<div class='clearfix info'> <div class='clearfix info'>
{{#link-to 'user' user class="avatar-link"}}<div class='avatar-wrapper'>{{avatar user imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div>{{/link-to}} {{#link-to 'user' user class="avatar-link"}}<div class='avatar-wrapper'>{{avatar user imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div>{{/link-to}}
<span class='time'>{{format-date path="created_at" leaveAgo="true"}}</span> <span class='time'>{{format-date created_at leaveAgo="true"}}</span>
<span class="title"> <span class="title">
<a href="{{unbound url}}">{{unbound title}}</a> <a href="{{unbound url}}">{{unbound title}}</a>
</span> </span>

View File

@ -11,10 +11,10 @@
{{outlet "modalBody"}} {{outlet "modalBody"}}
{{#each errors}} {{#each error in errors}}
<div class="alert alert-error"> <div class="alert alert-error">
<button class="close" data-dismiss="alert">×</button> <button class="close" data-dismiss="alert">×</button>
{{this}} {{error}}
</div> </div>
{{/each}} {{/each}}

View File

@ -58,15 +58,15 @@
{{#if user}} {{#if user}}
<div class="metadata"> <div class="metadata">
<h3><span class='desc'>{{i18n 'last_post'}}</span> {{format-date path="user.last_posted_at" leaveAgo="true"}}</h3> <h3><span class='desc'>{{i18n 'last_post'}}</span> {{format-date user.last_posted_at leaveAgo="true"}}</h3>
<h3><span class='desc'>{{i18n 'joined'}}</span> {{format-date path="user.created_at" leaveAgo="true"}}</h3> <h3><span class='desc'>{{i18n 'joined'}}</span> {{format-date user.created_at leaveAgo="true"}}</h3>
</div> </div>
{{/if}} {{/if}}
{{#if showBadges}} {{#if showBadges}}
<div class="badge-section"> <div class="badge-section">
{{#each user.featured_user_badges}} {{#each ub in user.featured_user_badges}}
{{user-badge badge=badge}} {{user-badge badge=ub.badge}}
{{/each}} {{/each}}
{{#if showMoreBadges}} {{#if showMoreBadges}}
{{#link-to 'user.badges' user class="btn more-user-badges"}} {{#link-to 'user.badges' user class="btn more-user-badges"}}

View File

@ -1,5 +1,5 @@
<section class='user-content user-badges-list'> <section class='user-content user-badges-list'>
{{#each}} {{#each ub in model}}
{{user-badge badge=badge count=count}} {{user-badge badge=ub.badge count=ub.count}}
{{/each}} {{/each}}
</section> </section>

View File

@ -14,11 +14,11 @@
</div> </div>
{{/if}} {{/if}}
{{#each itemController="notification"}} {{#each n in model itemController="notification"}}
<div {{bind-attr class=":item :notification read::unread"}}> <div {{bind-attr class=":item :notification read::n.unread"}}>
{{notification-item notification=this scope=scope}} {{notification-item notification=n scope=n.scope}}
<span class="time"> <span class="time">
{{format-date path="created_at" leaveAgo="true"}} {{format-date n.created_at leaveAgo="true"}}
</span> </span>
</div> </div>
{{/each}} {{/each}}

View File

@ -7,7 +7,7 @@
</div> </div>
</a> </a>
<span class="time"> <span class="time">
{{format-date path="created_at" leaveAgo="true"}} {{format-date created_at leaveAgo="true"}}
</span> </span>
<span class="title"> <span class="title">
<a href="{{unbound url}}">{{unbound topic_title}}</a> <a href="{{unbound url}}">{{unbound topic_title}}</a>
@ -17,7 +17,7 @@
</span> </span>
{{#if deleted}} {{#if deleted}}
<span class="delete-info"> <span class="delete-info">
<i class="fa fa-trash-o"></i> {{avatar deleted_by imageSize="tiny" extraClasses="actor" ignoreTitle="true"}} {{format-date path="deleted_at" leaveAgo="true"}} <i class="fa fa-trash-o"></i> {{avatar deleted_by imageSize="tiny" extraClasses="actor" ignoreTitle="true"}} {{format-date deleted_at leaveAgo="true"}}
</span> </span>
{{/if}} {{/if}}
</div> </div>

View File

@ -1,25 +1,25 @@
{{#each model.content}} {{#each item in model.content}}
<div {{bind-attr class=":item hidden deleted moderator_action"}}> <div {{bind-attr class=":item item.hidden item.deleted item.moderator_action"}}>
<div class='clearfix info'> <div class='clearfix info'>
<a href="{{unbound userUrl}}" data-user-card="{{unbound username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a> <a href="{{unbound item.userUrl}}" data-user-card="{{unbound item.username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar item imageSize="large" extraClasses="actor" ignoreTitle="true"}}</div></a>
<span class='time'>{{format-date path="created_at"}}</span> <span class='time'>{{format-date item.created_at}}</span>
<span class="title"> <span class="title">
<a href="{{unbound postUrl}}">{{unbound title}}</a> <a href="{{unbound item.postUrl}}">{{unbound item.title}}</a>
</span> </span>
<span class="category">{{category-link category}}</span> <span class="category">{{category-link item.category}}</span>
</div> </div>
<p class='excerpt'>{{{unbound excerpt}}}</p> <p class='excerpt'>{{{unbound item.excerpt}}}</p>
{{#each children}} {{#each child in item.children}}
<div class='child-actions'> <div class='child-actions'>
<i class="icon {{unbound icon}}"></i> <i class="icon {{unbound child.icon}}"></i>
{{#each items}} {{#each grandChild in child.items}}
{{#if removableBookmark}} {{#if grandChild.removableBookmark}}
<button class="btn btn-default remove-bookmark" {{action "removeBookmark" this}}> <button class="btn btn-default remove-bookmark" {{action "removeBookmark" grandChild}}>
{{fa-icon 'times'}} {{i18n "bookmarks.remove"}} {{fa-icon 'times'}} {{i18n "bookmarks.remove"}}
</button> </button>
{{/if}} {{/if}}
<a href="{{unbound userUrl}}" data-user-card="{{unbound username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar this imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a> <a href="{{unbound grandChild.userUrl}}" data-user-card="{{unbound grandChild.username}}" class='avatar-link'><div class='avatar-wrapper'>{{avatar grandChild imageSize="tiny" extraClasses="actor" ignoreTitle="true"}}</div></a>
{{#if edit_reason}} &mdash; <span class="edit-reason">{{unbound edit_reason}}</span>{{/if}} {{#if grandChild.edit_reason}} &mdash; <span class="edit-reason">{{unbound grandChild.edit_reason}}</span>{{/if}}
{{/each}} {{/each}}
</div> </div>
{{/each}} {{/each}}

View File

@ -121,8 +121,8 @@
{{#if custom_groups}} {{#if custom_groups}}
<dt>{{i18n 'groups.title' count=custom_groups.length}}</dt> <dt>{{i18n 'groups.title' count=custom_groups.length}}</dt>
<dd class='groups'> <dd class='groups'>
{{#each custom_groups}} {{#each group in custom_groups}}
<span>{{#link-to 'group' this class="group-link"}}{{name}}{{/link-to}}</span> <span>{{#link-to 'group' group class="group-link"}}{{group.name}}{{/link-to}}</span>
{{/each}} {{/each}}
</dd> </dd>
{{/if}} {{/if}}

View File

@ -1,9 +1,4 @@
window.ENV = { };
// These will help us migrate up to the new ember's default behavior
window.ENV = {
MANDATORY_SETTER: false,
FEATURES: {'query-params-new': true}
};
window.Discourse = {}; window.Discourse = {};
Discourse.SiteSettings = {}; Discourse.SiteSettings = {};

View File

@ -1,3 +1,4 @@
//= require ./discourse/helpers/register-unbound
//= require ./discourse/helpers/i18n_helpers //= require ./discourse/helpers/i18n_helpers
//= require ./discourse/mixins/ajax //= require ./discourse/mixins/ajax
//= require ./discourse //= require ./discourse

View File

@ -0,0 +1,16 @@
module Ember
module Handlebars
class Template < Tilt::Template
# Wrap in an IIFE in development mode to get the correct filename
def compile_ember_handlebars(string)
if ::Rails.env.development?
"(function() { try { return Ember.Handlebars.compile(#{indent(string).inspect}); } catch(err) { throw err; } })()"
else
"Handlebars.compile(#{indent(string).inspect});"
end
end
end
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff