Version bump
This commit is contained in:
commit
b124ada186
@ -150,7 +150,7 @@ GEM
|
||||
mail (2.6.6)
|
||||
mime-types (>= 1.16, < 4)
|
||||
memory_profiler (0.9.8)
|
||||
message_bus (2.0.3)
|
||||
message_bus (2.0.5)
|
||||
rack (>= 1.1.3)
|
||||
metaclass (0.0.4)
|
||||
method_source (0.8.2)
|
||||
@ -214,7 +214,7 @@ GEM
|
||||
omniauth-twitter (1.3.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
onebox (1.8.17)
|
||||
onebox (1.8.18)
|
||||
fast_blank (>= 1.0.0)
|
||||
htmlentities (~> 4.3)
|
||||
moneta (~> 1.0)
|
||||
|
||||
@ -236,7 +236,7 @@ export default Ember.Component.extend({
|
||||
const shortcuts = this.get('toolbar.shortcuts');
|
||||
|
||||
// for some reason I am having trouble bubbling this so hack it in
|
||||
mouseTrap.bind(['ctrl+/','command+/'], (event) =>{
|
||||
mouseTrap.bind(['ctrl+shift+s','command+shift+s'], (event) =>{
|
||||
this.appEvents.trigger('header:keyboard-trigger', {type: 'search', event});
|
||||
return true;
|
||||
});
|
||||
@ -259,7 +259,7 @@ export default Ember.Component.extend({
|
||||
|
||||
if (this.get('composerEvents')) {
|
||||
this.appEvents.on('composer:insert-block', text => this._addBlock(this._getSelected(), text));
|
||||
this.appEvents.on('composer:insert-text', text => this._addText(this._getSelected(), text));
|
||||
this.appEvents.on('composer:insert-text', (text, options) => this._addText(this._getSelected(), text, options));
|
||||
this.appEvents.on('composer:replace-text', (oldVal, newVal) => this._replaceText(oldVal, newVal));
|
||||
}
|
||||
this._mouseTrap = mouseTrap;
|
||||
@ -613,8 +613,22 @@ export default Ember.Component.extend({
|
||||
Ember.run.scheduleOnce("afterRender", () => $textarea.focus());
|
||||
},
|
||||
|
||||
_addText(sel, text) {
|
||||
_addText(sel, text, options) {
|
||||
const $textarea = this.$('textarea.d-editor-input');
|
||||
|
||||
if (options && options.ensureSpace) {
|
||||
if ((sel.pre + '').length > 0) {
|
||||
if (!sel.pre.match(/\s$/)) {
|
||||
text = ' ' + text;
|
||||
}
|
||||
}
|
||||
if ((sel.post + '').length > 0) {
|
||||
if (!sel.post.match(/^\s/)) {
|
||||
text = text + ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const insert = `${sel.pre}${text}`;
|
||||
const value = `${insert}${sel.post}`;
|
||||
this.set('value', value);
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['footer-message']
|
||||
});
|
||||
@ -19,13 +19,14 @@ function updateState(state, opts) {
|
||||
|
||||
export default Ember.Component.extend(bufferedProperty('editables'), {
|
||||
editing: propertyEqual('post', 'currentlyEditing'),
|
||||
editables: {},
|
||||
editables: null,
|
||||
_confirmDelete: updateState('rejected', {deleteUser: true}),
|
||||
|
||||
_initEditables: function() {
|
||||
const post = this.get('post');
|
||||
const postOptions = post.get('post_options');
|
||||
|
||||
this.set('editables', {});
|
||||
this.set('editables.raw', post.get('raw'));
|
||||
this.set('editables.category', post.get('category'));
|
||||
this.set('editables.category_id', post.get('category.id'));
|
||||
|
||||
@ -6,8 +6,8 @@ const bindings = {
|
||||
'!': {postAction: 'showFlags'},
|
||||
'#': {handler: 'goToPost', anonymous: true},
|
||||
'/': {handler: 'toggleSearch', anonymous: true},
|
||||
'ctrl+/': {handler: 'toggleSearch', anonymous: true},
|
||||
'command+/': {handler: 'toggleSearch', anonymous: true},
|
||||
'ctrl+shift+s': {handler: 'toggleSearch', anonymous: true},
|
||||
'command+shift+s': {handler: 'toggleSearch', anonymous: true},
|
||||
'=': {handler: 'toggleHamburgerMenu', anonymous: true},
|
||||
'?': {handler: 'showHelpModal', anonymous: true},
|
||||
'.': {click: '.alert.alert-info.clickable', anonymous: true}, // show incoming/updated topics
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
{{d-icon "check"}} {{i18n 'topics.bulk.dismiss_new'}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#footer-message education=footerEducation message=footerMessage tagName=""}}
|
||||
{{#footer-message education=footerEducation message=footerMessage}}
|
||||
{{#if latest}}
|
||||
{{#if canCreateTopicOnCategory}}<a href {{action "createTopic"}}>{{i18n 'topic.suggest_create_topic'}}</a>{{/if}}
|
||||
{{else if top}}
|
||||
|
||||
@ -40,29 +40,15 @@
|
||||
{{i18n 'topics.bulk.dismiss_new'}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if latest}}
|
||||
<div class="education">
|
||||
{{{footerEducation}}}
|
||||
</div>
|
||||
<h3>
|
||||
{{footerMessage}}
|
||||
{{#if model.can_create_topic}}<a href {{action "createTopic"}}>{{i18n 'topic.suggest_create_topic'}}</a>{{/if}}
|
||||
</h3>
|
||||
{{else}}
|
||||
{{#if top}}
|
||||
<h3>
|
||||
{{#link-to "discovery.categories"}}{{i18n 'topic.browse_all_categories'}}{{/link-to}}, {{#link-to 'discovery.latest'}}{{i18n 'topic.view_latest_topics'}}{{/link-to}} {{i18n 'or'}} {{i18n 'filters.top.other_periods'}}
|
||||
<br/>
|
||||
{{top-period-buttons period=period action="changePeriod"}}
|
||||
</h3>
|
||||
{{#footer-message education=footerEducation message=footerMessage}}
|
||||
{{#if latest}}
|
||||
{{#if canCreateTopicOnCategory}}<a href {{action "createTopic"}}>{{i18n 'topic.suggest_create_topic'}}</a>{{/if}}
|
||||
{{else if top}}
|
||||
{{#link-to "discovery.categories"}}{{i18n 'topic.browse_all_categories'}}{{/link-to}}, {{#link-to 'discovery.latest'}}{{i18n 'topic.view_latest_topics'}}{{/link-to}} {{i18n 'or'}} {{i18n 'filters.top.other_periods'}}
|
||||
{{top-period-buttons period=period action="changePeriod"}}
|
||||
{{else}}
|
||||
<div class="education">
|
||||
{{{footerEducation}}}
|
||||
</div>
|
||||
<h3>
|
||||
{{footerMessage}}{{#link-to "discovery.categories"}} {{i18n 'topic.browse_all_categories'}}{{/link-to}} {{i18n 'or'}} {{#link-to 'discovery.latest'}}{{i18n 'topic.view_latest_topics'}}{{/link-to}}
|
||||
</h3>
|
||||
{{#link-to "discovery.categories"}} {{i18n 'topic.browse_all_categories'}}{{/link-to}} {{i18n 'or'}} {{#link-to 'discovery.latest'}}{{i18n 'topic.view_latest_topics'}}{{/link-to}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/footer-message}}
|
||||
{{/if}}
|
||||
</footer>
|
||||
|
||||
@ -20,8 +20,8 @@ class Highlighted extends RawHtml {
|
||||
function createSearchResult({ type, linkField, builder }) {
|
||||
return createWidget(`search-result-${type}`, {
|
||||
html(attrs) {
|
||||
return attrs.results.map(r => {
|
||||
|
||||
return attrs.results.map(r => {
|
||||
let searchResultId;
|
||||
if (type === "topic") {
|
||||
searchResultId = r.get('topic_id');
|
||||
|
||||
@ -132,7 +132,7 @@ export default createWidget('search-menu', {
|
||||
noResults: searchData.noResults,
|
||||
results: searchData.results,
|
||||
invalidTerm: searchData.invalidTerm,
|
||||
searchContextEnabled: searchData.contextEnabled
|
||||
searchContextEnabled: searchData.contextEnabled,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -169,6 +169,75 @@ export default createWidget('search-menu', {
|
||||
this.sendWidgetAction('toggleSearchMenu');
|
||||
},
|
||||
|
||||
keyDown(e) {
|
||||
if (searchData.loading || searchData.noResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.which === 65 /* a */) {
|
||||
let focused = $('header .results .search-link:focus');
|
||||
if (focused.length === 1) {
|
||||
if ($('#reply-control.open').length === 1) {
|
||||
// add a link and focus composer
|
||||
|
||||
this.appEvents.trigger('composer:insert-text', focused[0].href, {ensureSpace: true});
|
||||
this.appEvents.trigger('header:keyboard-trigger', {type: 'search'});
|
||||
|
||||
e.preventDefault();
|
||||
$('#reply-control.open textarea').focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const up = e.which === 38;
|
||||
const down = e.which === 40;
|
||||
if (up || down) {
|
||||
|
||||
let focused = $('header .panel-body *:focus')[0];
|
||||
|
||||
if (!focused) {
|
||||
return;
|
||||
}
|
||||
|
||||
let links = $('header .panel-body .results a');
|
||||
let results = $('header .panel-body .results .search-link');
|
||||
|
||||
let prevResult;
|
||||
let result;
|
||||
|
||||
links.each((idx,item) => {
|
||||
if ($(item).hasClass('search-link')) {
|
||||
prevResult = item;
|
||||
}
|
||||
|
||||
if (item === focused) {
|
||||
result = prevResult;
|
||||
}
|
||||
});
|
||||
|
||||
let index = -1;
|
||||
|
||||
if (result) {
|
||||
index = results.index(result);
|
||||
}
|
||||
|
||||
if (index === -1 && down) {
|
||||
$('header .panel-body .search-link:first').focus();
|
||||
} else if (index === 0 && up) {
|
||||
$('header .panel-body input:first').focus();
|
||||
} else if (index > -1) {
|
||||
index += (down ? 1 : -1);
|
||||
if (index >= 0 && index < results.length) {
|
||||
$(results[index]).focus();
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
triggerSearch() {
|
||||
searchData.noResults = false;
|
||||
this.searchService().set('highlightTerm', searchData.term);
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
.menu-panel {
|
||||
border: 1px solid $primary-low;
|
||||
border: 1px solid $primary-low;
|
||||
box-shadow: 0 2px 2px rgba(0,0,0, .25);
|
||||
background-color: $secondary;
|
||||
z-index: 1100;
|
||||
@ -148,6 +148,7 @@
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.filter {
|
||||
padding: 0;
|
||||
&:hover {background: transparent;}
|
||||
|
||||
@ -92,6 +92,11 @@
|
||||
.user-table {
|
||||
margin-top: 30px;
|
||||
width: 100%;
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
.wrapper {
|
||||
display: table-row;
|
||||
}
|
||||
}
|
||||
|
||||
.user-navigation .nav-stacked .glyph {
|
||||
|
||||
@ -574,6 +574,9 @@ class PostsController < ApplicationController
|
||||
params[:skip_validations] = params[:skip_validations].to_s == "true"
|
||||
permitted << :skip_validations
|
||||
|
||||
params[:import_mode] = params[:import_mode].to_s == "true"
|
||||
permitted << :import_mode
|
||||
|
||||
# We allow `embed_url` via the API
|
||||
permitted << :embed_url
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ class Backup
|
||||
|
||||
def after_create_hook
|
||||
upload_to_s3 if SiteSetting.enable_s3_backups?
|
||||
DiscourseEvent.trigger(:backup_created)
|
||||
end
|
||||
|
||||
def after_remove_hook
|
||||
|
||||
@ -23,7 +23,13 @@ class CategoryFeaturedTopic < ActiveRecord::Base
|
||||
no_definitions: true
|
||||
}
|
||||
|
||||
# Add topics, even if they're in secured categories:
|
||||
# It may seem a bit odd that we are running 2 queries here, when admin
|
||||
# can clearly pull out all the topics needed.
|
||||
# We do so, so anonymous will ALWAYS get some topics
|
||||
# If we only fetched as admin we may have a situation where anon can see
|
||||
# no featured topics (all the previous 2x topics are only visible to admins)
|
||||
|
||||
# Add topics, even if they're in secured categories or invisible
|
||||
query = TopicQuery.new(CategoryFeaturedTopic.fake_admin, query_opts)
|
||||
results = query.list_category_topic_ids(c).uniq
|
||||
|
||||
|
||||
@ -139,7 +139,6 @@ module HasCustomFields
|
||||
end
|
||||
|
||||
def custom_fields
|
||||
|
||||
if @preloaded_custom_fields
|
||||
return @preloaded_proxy ||= PreloadedProxy.new(@preloaded_custom_fields)
|
||||
end
|
||||
@ -177,7 +176,10 @@ module HasCustomFields
|
||||
dup.delete(f.name)
|
||||
end
|
||||
else
|
||||
if dup[f.name] != f.value
|
||||
t = {}
|
||||
self.class.append_custom_field(t, f.name, f.value)
|
||||
|
||||
if dup[f.name] != t[f.name]
|
||||
f.destroy
|
||||
else
|
||||
dup.delete(f.name)
|
||||
|
||||
@ -2376,7 +2376,7 @@ en:
|
||||
hamburger_menu: '<b>=</b> Open hamburger menu'
|
||||
user_profile_menu: '<b>p</b> Open user menu'
|
||||
show_incoming_updated_topics: '<b>.</b> Show updated topics'
|
||||
search: '<b>/</b> or <b>ctrl</b>+<b>/</b> Search'
|
||||
search: '<b>/</b> or <b>ctrl</b>+<b>shift</b>+<b>s</b> Search'
|
||||
help: '<b>?</b> Open keyboard help'
|
||||
dismiss_new_posts: '<b>x</b>, <b>r</b> Dismiss New/Posts'
|
||||
dismiss_topics: '<b>x</b>, <b>t</b> Dismiss Topics'
|
||||
|
||||
@ -2424,7 +2424,7 @@ en:
|
||||
invited_group_to_private_message_body: |
|
||||
%{username} invited @%{group_name} to a message
|
||||
|
||||
> #### %{topic_title}
|
||||
> **%{topic_title}**
|
||||
>
|
||||
> %{topic_excerpt}
|
||||
|
||||
|
||||
@ -447,7 +447,7 @@ module Discourse
|
||||
|
||||
def self.reset_active_record_cache
|
||||
ActiveRecord::Base.connection.query_cache.clear
|
||||
(ActiveRecord::Base.connection.tables - %w[schema_migrations]).each do |table|
|
||||
(ActiveRecord::Base.connection.tables - %w[schema_migrations versions]).each do |table|
|
||||
table.classify.constantize.reset_column_information rescue nil
|
||||
end
|
||||
nil
|
||||
|
||||
@ -92,7 +92,7 @@ class Plugin::Instance
|
||||
|
||||
def whitelist_staff_user_custom_field(field)
|
||||
reloadable_patch do |plugin|
|
||||
User.register_plugin_staff_custom_field(field, plugin) if plugin.enabled?
|
||||
::User.register_plugin_staff_custom_field(field, plugin) if plugin.enabled?
|
||||
end
|
||||
end
|
||||
|
||||
@ -248,21 +248,27 @@ class Plugin::Instance
|
||||
end
|
||||
end
|
||||
|
||||
def register_category_custom_field_type(name, type)
|
||||
reloadable_patch do |plugin|
|
||||
Category.register_custom_field_type(name, type) if plugin.enabled?
|
||||
end
|
||||
end
|
||||
|
||||
def register_topic_custom_field_type(name, type)
|
||||
reloadable_patch do |plugin|
|
||||
Topic.register_custom_field_type(name, type) if plugin.enabled?
|
||||
::Topic.register_custom_field_type(name, type) if plugin.enabled?
|
||||
end
|
||||
end
|
||||
|
||||
def register_post_custom_field_type(name, type)
|
||||
reloadable_patch do |plugin|
|
||||
Post.register_custom_field_type(name, type) if plugin.enabled?
|
||||
::Post.register_custom_field_type(name, type) if plugin.enabled?
|
||||
end
|
||||
end
|
||||
|
||||
def register_group_custom_field_type(name, type)
|
||||
reloadable_patch do |plugin|
|
||||
Group.register_custom_field_type(name, type) if plugin.enabled?
|
||||
::Group.register_custom_field_type(name, type) if plugin.enabled?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -37,10 +37,14 @@ module Stylesheet
|
||||
end
|
||||
|
||||
root = Rails.root.to_s
|
||||
|
||||
listener_opts = { ignore: /xxxx/ }
|
||||
listener_opts[:force_polling] = true if ENV['FORCE_POLLING']
|
||||
|
||||
@paths.each do |watch|
|
||||
Thread.new do
|
||||
begin
|
||||
listener = Listen.to("#{root}/#{watch}", ignore: /xxxx/) do |modified, added, _|
|
||||
listener = Listen.to("#{root}/#{watch}", listener_opts) do |modified, added, _|
|
||||
paths = [modified, added].flatten
|
||||
paths.compact!
|
||||
paths.map! { |long| long[(root.length + 1)..-1] }
|
||||
|
||||
@ -5,7 +5,7 @@ module Discourse
|
||||
MAJOR = 1
|
||||
MINOR = 9
|
||||
TINY = 0
|
||||
PRE = 'beta6'
|
||||
PRE = 'beta7'
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
||||
end
|
||||
|
||||
@ -142,6 +142,16 @@ describe HasCustomFields do
|
||||
test_item.reload
|
||||
|
||||
expect(test_item.custom_fields).to eq("bool" => true, "int" => 1, "json" => { "foo" => "bar" })
|
||||
|
||||
before_ids = CustomFieldsTestItemCustomField.where(custom_fields_test_item_id: test_item.id).pluck(:id)
|
||||
|
||||
test_item.custom_fields["bool"] = false
|
||||
test_item.save
|
||||
|
||||
after_ids = CustomFieldsTestItemCustomField.where(custom_fields_test_item_id: test_item.id).pluck(:id)
|
||||
|
||||
# we updated only 1 custom field, so there should be only 1 different id
|
||||
expect((before_ids - after_ids).size).to eq(1)
|
||||
end
|
||||
|
||||
it "simple modifications don't interfere" do
|
||||
|
||||
@ -510,7 +510,7 @@ describe PostsController do
|
||||
end
|
||||
|
||||
it "toggle wiki status should create a new version" do
|
||||
admin = log_in(:admin)
|
||||
_admin = log_in(:admin)
|
||||
another_user = Fabricate(:user)
|
||||
another_post = Fabricate(:post, user: another_user)
|
||||
|
||||
@ -520,7 +520,7 @@ describe PostsController do
|
||||
expect { xhr :put, :wiki, post_id: another_post.id, wiki: 'false' }
|
||||
.to change { another_post.reload.version }.by(-1)
|
||||
|
||||
another_admin = log_in(:admin)
|
||||
_another_admin = log_in(:admin)
|
||||
|
||||
expect { xhr :put, :wiki, post_id: another_post.id, wiki: 'true' }
|
||||
.to change { another_post.reload.version }.by(1)
|
||||
@ -631,6 +631,46 @@ describe PostsController do
|
||||
|
||||
expect(response.body).to eq(original)
|
||||
end
|
||||
|
||||
it 'allows to create posts in import_mode' do
|
||||
NotificationEmailer.enable
|
||||
post = Fabricate(:post)
|
||||
user = Fabricate(:user)
|
||||
master_key = ApiKey.create_master_key.key
|
||||
|
||||
xhr :post, :create,
|
||||
api_username: user.username,
|
||||
api_key: master_key,
|
||||
raw: 'this is test reply 1',
|
||||
topic_id: post.topic.id,
|
||||
reply_to_post_number: 1
|
||||
|
||||
expect(response).to be_success
|
||||
expect(post.topic.user.notifications.count).to eq(1)
|
||||
post.topic.user.notifications.destroy_all
|
||||
|
||||
xhr :post, :create,
|
||||
api_username: user.username,
|
||||
api_key: master_key,
|
||||
raw: 'this is test reply 2',
|
||||
topic_id: post.topic.id,
|
||||
reply_to_post_number: 1,
|
||||
import_mode: true
|
||||
|
||||
expect(response).to be_success
|
||||
expect(post.topic.user.notifications.count).to eq(0)
|
||||
|
||||
xhr :post, :create,
|
||||
api_username: user.username,
|
||||
api_key: master_key,
|
||||
raw: 'this is test reply 3',
|
||||
topic_id: post.topic.id,
|
||||
reply_to_post_number: 1,
|
||||
import_mode: false
|
||||
|
||||
expect(response).to be_success
|
||||
expect(post.topic.user.notifications.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when logged in' do
|
||||
|
||||
@ -34,7 +34,7 @@ describe CategoryFeaturedTopic do
|
||||
|
||||
it 'should feature stuff in the correct order' do
|
||||
category = Fabricate(:category, num_featured_topics: 2)
|
||||
t5 = Fabricate(:topic, category_id: category.id, bumped_at: 12.minutes.ago)
|
||||
_t5 = Fabricate(:topic, category_id: category.id, bumped_at: 12.minutes.ago)
|
||||
t4 = Fabricate(:topic, category_id: category.id, bumped_at: 10.minutes.ago)
|
||||
t3 = Fabricate(:topic, category_id: category.id, bumped_at: 7.minutes.ago)
|
||||
t2 = Fabricate(:topic, category_id: category.id, bumped_at: 4.minutes.ago)
|
||||
@ -45,7 +45,7 @@ describe CategoryFeaturedTopic do
|
||||
|
||||
# Should find more than we need: pinned topics first, then num_featured_topics * 2
|
||||
expect(
|
||||
CategoryFeaturedTopic.where(category_id: category.id).pluck(:topic_id)
|
||||
CategoryFeaturedTopic.where(category_id: category.id).order('rank asc').pluck(:topic_id)
|
||||
).to eq([pinned.id, t2.id, t1.id, t3.id, t4.id])
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user