Merge branch 'master' of github.com:discourse/discourse
This commit is contained in:
commit
500a24ebf9
|
@ -89,6 +89,13 @@ GIT
|
||||||
rake
|
rake
|
||||||
rake-compiler
|
rake-compiler
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/MiniProfiler/rack-mini-profiler.git
|
||||||
|
revision: e08b751091a41f0066a1b28bd4e2b9b3480a1c1b
|
||||||
|
specs:
|
||||||
|
rack-mini-profiler (0.1.31)
|
||||||
|
rack (>= 1.1.3)
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/SamSaffron/annotate_models.git
|
remote: https://github.com/SamSaffron/annotate_models.git
|
||||||
revision: ebe4ba7e3f6ceeb43e4e40078da2b261a1bb71b2
|
revision: ebe4ba7e3f6ceeb43e4e40078da2b261a1bb71b2
|
||||||
|
@ -146,12 +153,6 @@ GIT
|
||||||
activerecord (>= 3.0.0)
|
activerecord (>= 3.0.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
|
||||||
PATH
|
|
||||||
remote: /Users/sam/Source/rack-mini-profiler
|
|
||||||
specs:
|
|
||||||
rack-mini-profiler (0.1.31)
|
|
||||||
rack (>= 1.1.3)
|
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: vendor/gems/discourse_emoji
|
remote: vendor/gems/discourse_emoji
|
||||||
specs:
|
specs:
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@namespace Discourse
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.AdminEmailIndexController = Discourse.Controller.extend(Discourse.Presence, {
|
Discourse.AdminEmailIndexController = Discourse.Controller.extend({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Is the "send test email" button disabled?
|
Is the "send test email" button disabled?
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@namespace Discourse
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.AdminEmailPreviewDigestController = Discourse.ObjectController.extend(Discourse.Presence, {
|
Discourse.AdminEmailPreviewDigestController = Discourse.ObjectController.extend({
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
var model = this.get('model');
|
var model = this.get('model');
|
||||||
|
|
|
@ -208,6 +208,17 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add an initializer hook for after the Discourse Application starts up.
|
||||||
|
|
||||||
|
@method addInitializer
|
||||||
|
@param {Function} init the initializer to add.
|
||||||
|
**/
|
||||||
|
addInitializer: function(init) {
|
||||||
|
Discourse.initializers = Discourse.initializers || [];
|
||||||
|
Discourse.initializers.push(init);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Start up the Discourse application.
|
Start up the Discourse application.
|
||||||
|
|
||||||
|
@ -223,6 +234,12 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
// Developer specific functions
|
// Developer specific functions
|
||||||
Discourse.Development.observeLiveChanges();
|
Discourse.Development.observeLiveChanges();
|
||||||
Discourse.subscribeUserToNotifications();
|
Discourse.subscribeUserToNotifications();
|
||||||
|
|
||||||
|
if (Discourse.initializers) {
|
||||||
|
Discourse.initializers.forEach(function (init) {
|
||||||
|
init.call(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
@namespace Discourse
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.ComposerView = Discourse.View.extend({
|
Discourse.ComposerView = Discourse.View.extend(Ember.Evented, {
|
||||||
templateName: 'composer',
|
templateName: 'composer',
|
||||||
elementId: 'reply-control',
|
elementId: 'reply-control',
|
||||||
classNameBindings: ['model.creatingPrivateMessage:private-message',
|
classNameBindings: ['model.creatingPrivateMessage:private-message',
|
||||||
|
@ -49,18 +49,17 @@ Discourse.ComposerView = Discourse.View.extend({
|
||||||
}.property('model.createdPost'),
|
}.property('model.createdPost'),
|
||||||
|
|
||||||
observeReplyChanges: function() {
|
observeReplyChanges: function() {
|
||||||
var composerView = this;
|
var self = this;
|
||||||
if (this.get('model.hidePreview')) return;
|
if (this.get('model.hidePreview')) return;
|
||||||
Ember.run.next(null, function() {
|
Ember.run.next(function() {
|
||||||
var $wmdPreview, caretPosition;
|
if (self.editor) {
|
||||||
if (composerView.editor) {
|
self.editor.refreshPreview();
|
||||||
composerView.editor.refreshPreview();
|
|
||||||
// if the caret is on the last line ensure preview scrolled to bottom
|
// if the caret is on the last line ensure preview scrolled to bottom
|
||||||
caretPosition = Discourse.Utilities.caretPosition(composerView.wmdInput[0]);
|
var caretPosition = Discourse.Utilities.caretPosition(self.wmdInput[0]);
|
||||||
if (!composerView.wmdInput.val().substring(caretPosition).match(/\n/)) {
|
if (!self.wmdInput.val().substring(caretPosition).match(/\n/)) {
|
||||||
$wmdPreview = $('#wmd-preview');
|
var $wmdPreview = $('#wmd-preview');
|
||||||
if ($wmdPreview.is(':visible')) {
|
if ($wmdPreview.is(':visible')) {
|
||||||
return $wmdPreview.scrollTop($wmdPreview[0].scrollHeight);
|
$wmdPreview.scrollTop($wmdPreview[0].scrollHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +128,8 @@ Discourse.ComposerView = Discourse.View.extend({
|
||||||
|
|
||||||
Discourse.SyntaxHighlighting.apply($wmdPreview);
|
Discourse.SyntaxHighlighting.apply($wmdPreview);
|
||||||
|
|
||||||
var post = this.get('model.post');
|
var post = this.get('model.post'),
|
||||||
var refresh = false;
|
refresh = false;
|
||||||
|
|
||||||
// If we are editing a post, we'll refresh its contents once. This is a feature that
|
// If we are editing a post, we'll refresh its contents once. This is a feature that
|
||||||
// allows a user to refresh its contents once.
|
// allows a user to refresh its contents once.
|
||||||
|
@ -146,6 +145,8 @@ Discourse.ComposerView = Discourse.View.extend({
|
||||||
$('span.mention', $wmdPreview).each(function(i, e) {
|
$('span.mention', $wmdPreview).each(function(i, e) {
|
||||||
Discourse.Mention.load(e, refresh);
|
Discourse.Mention.load(e, refresh);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.trigger('previewRefreshed', $wmdPreview);
|
||||||
}, 100),
|
}, 100),
|
||||||
|
|
||||||
initEditor: function() {
|
initEditor: function() {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@namespace Discourse
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.PostView = Discourse.GroupedView.extend({
|
Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, {
|
||||||
classNames: ['topic-post', 'clearfix'],
|
classNames: ['topic-post', 'clearfix'],
|
||||||
templateName: 'post',
|
templateName: 'post',
|
||||||
classNameBindings: ['postTypeClass',
|
classNameBindings: ['postTypeClass',
|
||||||
|
@ -193,8 +193,9 @@ Discourse.PostView = Discourse.GroupedView.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
var $post = this.$();
|
var $post = this.$(),
|
||||||
var post = this.get('post');
|
post = this.get('post');
|
||||||
|
|
||||||
this.showLinkCounts();
|
this.showLinkCounts();
|
||||||
|
|
||||||
// Track this post
|
// Track this post
|
||||||
|
@ -204,6 +205,8 @@ Discourse.PostView = Discourse.GroupedView.extend({
|
||||||
Discourse.SyntaxHighlighting.apply($post);
|
Discourse.SyntaxHighlighting.apply($post);
|
||||||
Discourse.Lightbox.apply($post);
|
Discourse.Lightbox.apply($post);
|
||||||
|
|
||||||
|
this.trigger('postViewInserted', $post);
|
||||||
|
|
||||||
// Find all the quotes
|
// Find all the quotes
|
||||||
this.insertQuoteControls();
|
this.insertQuoteControls();
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ span.badge-posts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
button.create {
|
button.create {
|
||||||
float: right !important;
|
float: right !important;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
|
@ -449,6 +451,8 @@ blockquote {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
color: #323232;
|
color: #323232;
|
||||||
font-family: "FontAwesome";
|
font-family: "FontAwesome";
|
||||||
|
position: relative;
|
||||||
|
z-index: 20;
|
||||||
}
|
}
|
||||||
.back:before {
|
.back:before {
|
||||||
content: "\f062";
|
content: "\f062";
|
||||||
|
|
|
@ -284,7 +284,8 @@ class Post < ActiveRecord::Base
|
||||||
AND p2.user_id <> post_timings.user_id
|
AND p2.user_id <> post_timings.user_id
|
||||||
GROUP BY post_timings.topic_id, post_timings.post_number) AS x
|
GROUP BY post_timings.topic_id, post_timings.post_number) AS x
|
||||||
WHERE x.topic_id = posts.topic_id
|
WHERE x.topic_id = posts.topic_id
|
||||||
AND x.post_number = posts.post_number")
|
AND x.post_number = posts.post_number
|
||||||
|
AND (posts.avg_time <> (x.gmean / 1000)::int OR posts.avg_time IS NULL)")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -778,7 +778,7 @@ ru:
|
||||||
|
|
||||||
Если вам интересно, пройдите по ссылке ниже, чтобы попасть в обсуждение:
|
Если вам интересно, пройдите по ссылке ниже, чтобы попасть в обсуждение:
|
||||||
|
|
||||||
[Visit %{site_name}[1]
|
[Visit %{site_name}][1]
|
||||||
|
|
||||||
Вы приглашены доверенным пользователем, поэтому сразу сможете разместить свой ответ без входа на сайт.
|
Вы приглашены доверенным пользователем, поэтому сразу сможете разместить свой ответ без входа на сайт.
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ module Oneboxer
|
||||||
Entry.new(/^https?:\/\/(?:www\.)?screenr\.com\/.+/),
|
Entry.new(/^https?:\/\/(?:www\.)?screenr\.com\/.+/),
|
||||||
Entry.new(/^https?:\/\/(?:www\.)?tumblr\.com\/.+/, false),
|
Entry.new(/^https?:\/\/(?:www\.)?tumblr\.com\/.+/, false),
|
||||||
Entry.new(/^https?:\/\/(?:www\.)?howtogeek\.com\/.+/, false),
|
Entry.new(/^https?:\/\/(?:www\.)?howtogeek\.com\/.+/, false),
|
||||||
|
Entry.new(/^https?:\/\/(?:www\.)?screencast\.com\/.+/),
|
||||||
Entry.new(/\/\d{4}\/\d{2}\/\d{2}\//, false), # wordpress
|
Entry.new(/\/\d{4}\/\d{2}\/\d{2}\//, false), # wordpress
|
||||||
Entry.new(/^https?:\/\/[^\/]+\/t\/[^\/]+\/\d+(\/\d+)?(\?.*)?$/),
|
Entry.new(/^https?:\/\/[^\/]+\/t\/[^\/]+\/\d+(\/\d+)?(\?.*)?$/),
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,8 @@ class Plugin::Instance
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_extra_automatic_assets(good_paths)
|
def delete_extra_automatic_assets(good_paths)
|
||||||
|
return unless Dir.exists? auto_generated_path
|
||||||
|
|
||||||
filenames = good_paths.map{|f| File.basename(f)}
|
filenames = good_paths.map{|f| File.basename(f)}
|
||||||
# nuke old files
|
# nuke old files
|
||||||
Dir.foreach(auto_generated_path) do |p|
|
Dir.foreach(auto_generated_path) do |p|
|
||||||
|
@ -102,7 +104,7 @@ class Plugin::Instance
|
||||||
|
|
||||||
def automatic_assets
|
def automatic_assets
|
||||||
css = ""
|
css = ""
|
||||||
js = "(function(){"
|
js = ""
|
||||||
|
|
||||||
css = @styles.join("\n") if @styles
|
css = @styles.join("\n") if @styles
|
||||||
js = @javascripts.join("\n") if @javascripts
|
js = @javascripts.join("\n") if @javascripts
|
||||||
|
@ -127,10 +129,14 @@ class Plugin::Instance
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
js << "})();"
|
# Generate an IIFE for the JS
|
||||||
|
js = "(function(){#{js}})();" if js.present?
|
||||||
|
|
||||||
# TODO don't serve blank assets
|
result = []
|
||||||
[[css,"css"],[js,"js"]].map do |asset, extension|
|
result << [css, 'css'] if css.present?
|
||||||
|
result << [js, 'js'] if js.present?
|
||||||
|
|
||||||
|
result.map do |asset, extension|
|
||||||
hash = Digest::SHA1.hexdigest asset
|
hash = Digest::SHA1.hexdigest asset
|
||||||
["#{auto_generated_path}/plugin_#{hash}.#{extension}", asset]
|
["#{auto_generated_path}/plugin_#{hash}.#{extension}", asset]
|
||||||
end
|
end
|
||||||
|
|
|
@ -176,7 +176,7 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_new_in_category(category)
|
def list_new_in_category(category)
|
||||||
create_list(:new_in_category) {|l| l.where(category_id: category.id).by_newest.first(25)}
|
create_list(:new_in_category, unordered: true) {|l| l.where(category_id: category.id).by_newest.first(25)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.new_filter(list, treat_as_new_topic_start_date)
|
def self.new_filter(list, treat_as_new_topic_start_date)
|
||||||
|
|
|
@ -34,7 +34,7 @@ describe Plugin::Instance do
|
||||||
auth_provider.authenticator.name.should == 'ubuntu'
|
auth_provider.authenticator.name.should == 'ubuntu'
|
||||||
|
|
||||||
# calls ensure_assets! make sure they are there
|
# calls ensure_assets! make sure they are there
|
||||||
plugin.assets.count.should == 2
|
plugin.assets.count.should == 1
|
||||||
plugin.assets.each do |a|
|
plugin.assets.each do |a|
|
||||||
File.exists?(a).should be_true
|
File.exists?(a).should be_true
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
module("Discourse.AdminEmailIndexController");
|
||||||
|
|
||||||
|
test("mixes in Discourse.Presence", function() {
|
||||||
|
ok(Discourse.Presence.detect(Discourse.AdminEmailIndexController.create()));
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
module("Discourse.AdminEmailPreviewDigestController");
|
||||||
|
|
||||||
|
test("mixes in Discourse.Presence", function() {
|
||||||
|
ok(Discourse.Presence.detect(Discourse.AdminEmailPreviewDigestController.create()));
|
||||||
|
});
|
Loading…
Reference in New Issue