diff --git a/app/assets/javascripts/discourse/controllers/composer_controller.js b/app/assets/javascripts/discourse/controllers/composer_controller.js index 22cb510b056..1b1df2f0a16 100644 --- a/app/assets/javascripts/discourse/controllers/composer_controller.js +++ b/app/assets/javascripts/discourse/controllers/composer_controller.js @@ -18,11 +18,13 @@ Discourse.ComposerController = Discourse.Controller.extend({ this.get('content').importQuote(); }, + resetDraftStatus: function() { + this.get('content').resetDraftStatus(); + }, + appendText: function(text) { var c = this.get('content'); - if (c) { - c.appendText(text); - } + if (c) return c.appendText(text); }, save: function(force) { @@ -91,6 +93,7 @@ Discourse.ComposerController = Discourse.Controller.extend({ }); }, +<<<<<<< HEAD closeEducation: function() { this.set('educationClosed', true); }, @@ -161,6 +164,7 @@ Discourse.ComposerController = Discourse.Controller.extend({ Discourse.Topic.findSimilarTo(title, body).then(function (topics) { composerController.set('similarTopics', topics); }); + }, saveDraft: function() { diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js index 4faa88a8693..6add03e2730 100644 --- a/app/assets/javascripts/discourse/models/composer.js +++ b/app/assets/javascripts/discourse/models/composer.js @@ -28,7 +28,7 @@ Discourse.Composer = Discourse.Model.extend({ this._super(); var val = Discourse.KeyValueStore.get('composer.showPreview') || 'true'; this.set('showPreview', val === 'true'); - return this.set('archetypeId', Discourse.get('site.default_archetype')); + this.set('archetypeId', Discourse.get('site.default_archetype')); }, creatingTopic: (function() { @@ -142,10 +142,7 @@ Discourse.Composer = Discourse.Model.extend({ }).property('action', 'post', 'topic', 'topic.title'), toggleText: (function() { - if (this.get('showPreview')) { - return Em.String.i18n('composer.hide_preview'); - } - return Em.String.i18n('composer.show_preview'); + return this.get('showPreview') ? Em.String.i18n('composer.hide_preview') : Em.String.i18n('composer.show_preview'); }).property('showPreview'), hidePreview: (function() { @@ -159,14 +156,11 @@ Discourse.Composer = Discourse.Model.extend({ if (this.get('loading')) return true; // Title is required on new posts - if (this.get('creatingTopic')) { - if (this.blank('title')) return true; - if (this.get('title').trim().length < Discourse.SiteSettings.min_topic_title_length) return true; - } + if (this.get('creatingTopic') && this.get('titleLength') < Discourse.SiteSettings.min_topic_title_length) return true; // Otherwise just reply is required - if (this.blank('reply')) return true; - if (this.get('reply').trim().length < Discourse.SiteSettings.min_post_length) return true; + if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return true; + return false; }).property('reply', 'title', 'creatingTopic', 'loading'), @@ -434,6 +428,7 @@ Discourse.Composer = Discourse.Model.extend({ saveDraft: function() { if (this.get('disableDrafts')) return; if (!this.get('reply')) return; + if (this.get('titleLength') < Discourse.SiteSettings.min_topic_title_length) return; if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return; var data = { @@ -453,28 +448,38 @@ Discourse.Composer = Discourse.Model.extend({ return Discourse.Draft.save(this.get('draftKey'), this.get('draftSequence'), data).then((function() { composer.set('draftStatus', Em.String.i18n('composer.saved_draft_tip')); }), (function() { - composer.set('draftStatus', 'drafts offline'); + composer.set('draftStatus', Em.String.i18n('composer.drafts_offline')); })); }, resetDraftStatus: (function() { - var len = Discourse.SiteSettings.min_post_length, - replyLength = this.get('replyLength'); - - if (replyLength === 0) { - this.set('draftStatus', Em.String.i18n('composer.min_length.at_least', { n: len })); - } else if (replyLength < len) { - this.set('draftStatus', Em.String.i18n('composer.min_length.more', { n: len - replyLength })); - } else { - this.set('draftStatus', null); + // 'title' is focused + if ($('#reply-title').is(':focus')) { + var titleDiff = Discourse.SiteSettings.min_topic_title_length - this.get('titleLength'); + if (titleDiff > 0) { + return this.set('draftStatus', Em.String.i18n('composer.min_length.need_more_for_title', { n: titleDiff })); + } + // 'reply' is focused + } else if ($('#wmd-input').is(':focus')) { + var replyDiff = Discourse.SiteSettings.min_post_length - this.get('replyLength'); + if (replyDiff > 0) { + return this.set('draftStatus', Em.String.i18n('composer.min_length.need_more_for_reply', { n: replyDiff })); + } } + // hide the counters if the currently focused text field is OK + this.set('draftStatus', null); }).observes('reply', 'title'), - blank: function(prop) { - var p = this.get(prop); - return !(p && p.length > 0); - }, + /** + Computes the length of the title minus non-significant whitespaces + + @property titleLength + **/ + titleLength: function() { + var title = this.get('title') || ""; + return title.replace(/\s+/img, " ").trim().length; + }.property('title'), /** Computes the length of the reply minus the quote(s) and non-significant whitespaces @@ -482,8 +487,7 @@ Discourse.Composer = Discourse.Model.extend({ @property replyLength **/ replyLength: function() { - var reply = this.get('reply'); - if(!reply) reply = ""; + var reply = this.get('reply') || ""; while (Discourse.BBCode.QUOTE_REGEXP.test(reply)) { reply = reply.replace(Discourse.BBCode.QUOTE_REGEXP, ""); } return reply.replace(/\s+/img, " ").trim().length; }.property('reply') @@ -543,5 +547,3 @@ Discourse.Composer.reopenClass({ // Draft key REPLY_AS_NEW_TOPIC_KEY: REPLY_AS_NEW_TOPIC_KEY }); - - diff --git a/app/assets/javascripts/discourse/templates/composer.js.handlebars b/app/assets/javascripts/discourse/templates/composer.js.handlebars index fc386e2d336..e9aece095c8 100644 --- a/app/assets/javascripts/discourse/templates/composer.js.handlebars +++ b/app/assets/javascripts/discourse/templates/composer.js.handlebars @@ -27,7 +27,6 @@ {{#if content.editTitle}}
- {{#if content.creatingPrivateMessage}} {{view Discourse.TextField id="private-message-users" class="span8" placeholderKey="composer.users_placeholder"}} {{/if}} @@ -41,7 +40,6 @@
{{/if}} -
@@ -53,7 +51,6 @@ {{#if Discourse.currentUser}} {{{content.toggleText}}}
- {{/if}}
@@ -61,7 +58,6 @@
{{i18n cancel}} - {{#if view.loadingImage}}
{{i18n image_selector.uploading_image}} {{view.uploadProgress}}% {{i18n cancel}} diff --git a/app/assets/javascripts/discourse/views/composer_view.js b/app/assets/javascripts/discourse/views/composer_view.js index 7f1a0fed502..cc895bc65ce 100644 --- a/app/assets/javascripts/discourse/views/composer_view.js +++ b/app/assets/javascripts/discourse/views/composer_view.js @@ -85,7 +85,13 @@ Discourse.ComposerView = Discourse.View.extend({ $('.composer-popup').css('bottom', sizePx); }, - resize: function() { + focusIn: (function() { + var controller = this.get('controller'); + if(controller) controller.resetDraftStatus(); + }), + + + resize: (function() { // this still needs to wait on animations, need a clean way to do that return Em.run.next(null, function() { var replyControl = $('#reply-control'); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index ec06ed150f4..cf28c285cbb 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -268,10 +268,11 @@ en: saved_draft_tip: "saved" saved_local_draft_tip: "saved locally" similar_topics: "Similar Topics" + drafts_offline: "drafts offline" min_length: - at_least: "enter at least {{n}} characters" - more: "{{n}} to go..." + need_more_for_title: "{{n}} to go for the title" + need_more_for_reply: "{{n}} to go for the reply" save_edit: "Save Edit" reply_original: "Reply on Original Topic" diff --git a/config/locales/client.fr.yml b/config/locales/client.fr.yml index d05d6cdd837..beaf357e917 100644 --- a/config/locales/client.fr.yml +++ b/config/locales/client.fr.yml @@ -271,10 +271,11 @@ fr: saving_draft_tip: "sauvegarde..." saved_draft_tip: "sauvegardé" saved_local_draft_tip: "sauvegardé en local" + drafts_offline: "sauvegardé hors ligne" min_length: - at_least: "Saisir au moins {{n}} caractères" - more: "{{n}} restants..." + need_more_for_title: "{{n}} caractères restant pour le titre" + need_more_for_reply: "{{n}} caractères restant pour le message" save_edit: "Sauvegarder la modification" reply_original: Répondre à la discussion initiale diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index 10a85a3dec4..f451d6df6af 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -52,7 +52,6 @@ describe Report do it 'returns correct data' do report.data[0][:y].should == 1 - pending 'breaks in my local 2.0 setup (Sam) - Neil please fix - report.data[1] is nil' report.data[1][:y].should == 2 end end