diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js index a9dda18c5ac..8f6d2d3ca5d 100644 --- a/app/assets/javascripts/discourse/models/composer.js +++ b/app/assets/javascripts/discourse/models/composer.js @@ -179,12 +179,12 @@ Discourse.Composer = Discourse.Model.extend({ } // reply is always required - if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return true; + if (this.get('missingReplyCharacters') > 0) return true; if (this.get('canCategorize') && !Discourse.SiteSettings.allow_uncategorized_topics && !this.get('categoryName')) return true; return false; - }.property('loading', 'editTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryName'), + }.property('loading', 'editTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryName', 'missingReplyCharacters'), titleLengthValid: function() { if (this.get('creatingPrivateMessage')) { @@ -193,7 +193,7 @@ Discourse.Composer = Discourse.Model.extend({ if (this.get('titleLength') < Discourse.SiteSettings.min_topic_title_length) return false; } return (this.get('titleLength') <= Discourse.SiteSettings.max_topic_title_length); - }.property('titleLength'), + }.property('creatingPrivateMessage', 'titleLength'), // The text for the save button saveText: function() { @@ -531,12 +531,21 @@ Discourse.Composer = Discourse.Model.extend({ @property missingTitleCharacters **/ missingTitleCharacters: function() { + return this.get('minimumTitleLength') - this.get('titleLength'); + }.property('minimumTitleLength', 'titleLength'), + + /** + Minimum number of characters for a title to be valid. + + @property minimumTitleLength + **/ + minimumTitleLength: function() { if (this.get('creatingPrivateMessage')) { - return Discourse.SiteSettings.min_private_message_title_length - this.get('titleLength'); + return Discourse.SiteSettings.min_private_message_title_length; } else { - return Discourse.SiteSettings.min_topic_title_length - this.get('titleLength'); + return Discourse.SiteSettings.min_topic_title_length; } - }.property('titleLength'), + }.property('creatingPrivateMessage'), /** @@ -545,8 +554,21 @@ Discourse.Composer = Discourse.Model.extend({ @property missingReplyCharacters **/ missingReplyCharacters: function() { - return Discourse.SiteSettings.min_post_length - this.get('replyLength'); - }.property('replyLength'), + return this.get('minimumPostLength') - this.get('replyLength'); + }.property('minimumPostLength', 'replyLength'), + + /** + Minimum number of characters for a post body to be valid. + + @property minimumPostLength + **/ + minimumPostLength: function() { + if( this.get('creatingPrivateMessage') ) { + return Discourse.SiteSettings.min_private_message_post_length; + } else { + return Discourse.SiteSettings.min_post_length; + } + }.property('creatingPrivateMessage'), /** Computes the length of the title minus non-significant whitespaces diff --git a/app/assets/javascripts/discourse/views/composer_view.js b/app/assets/javascripts/discourse/views/composer_view.js index 009d3c18e43..c531dfa8591 100644 --- a/app/assets/javascripts/discourse/views/composer_view.js +++ b/app/assets/javascripts/discourse/views/composer_view.js @@ -368,20 +368,21 @@ Discourse.ComposerView = Discourse.View.extend({ }, titleValidation: function() { - var title = this.get('content.title'), reason; - var minLength = (this.get('content.creatingPrivateMessage') ? Discourse.SiteSettings.min_private_message_title_length : Discourse.SiteSettings.min_topic_title_length); - if( !title || title.length < 1 ){ + var titleLength = this.get('content.titleLength'), + missingChars = this.get('content.missingTitleCharacters'), + reason; + if( titleLength < 1 ){ reason = Em.String.i18n('composer.error.title_missing'); - } else if( title.length < minLength ) { - reason = Em.String.i18n('composer.error.title_too_short', {min: minLength}) - } else if( title.length > Discourse.SiteSettings.max_topic_title_length ) { - reason = Em.String.i18n('composer.error.title_too_long', {max: Discourse.SiteSettings.max_topic_title_length}) + } else if( missingChars > 0 ) { + reason = Em.String.i18n('composer.error.title_too_short', {min: this.get('content.minimumTitleLength')}); + } else if( titleLength > Discourse.SiteSettings.max_topic_title_length ) { + reason = Em.String.i18n('composer.error.title_too_long', {max: Discourse.SiteSettings.max_topic_title_length}); } if( reason ) { return Discourse.InputValidation.create({ failed: true, reason: reason }); } - }.property('content.title'), + }.property('content.titleLength', 'content.missingTitleCharacters', 'content.minimumTitleLength'), categoryValidation: function() { if( !Discourse.SiteSettings.allow_uncategorized_topics && !this.get('content.categoryName')) { @@ -390,17 +391,19 @@ Discourse.ComposerView = Discourse.View.extend({ }.property('content.categoryName'), replyValidation: function() { - var reply = this.get('content.reply'), reason; - if( !reply || reply.length < 1 ){ + var replyLength = this.get('content.replyLength'), + missingChars = this.get('content.missingReplyCharacters'), + reason; + if( replyLength < 1 ){ reason = Em.String.i18n('composer.error.post_missing'); - } else if( reply.length < Discourse.SiteSettings.min_post_length ) { - reason = Em.String.i18n('composer.error.post_length', {min: Discourse.SiteSettings.min_post_length}) + } else if( missingChars > 0 ) { + reason = Em.String.i18n('composer.error.post_length', {min: this.get('content.minimumPostLength')}); } if( reason ) { return Discourse.InputValidation.create({ failed: true, reason: reason }); } - }.property('content.reply') + }.property('content.reply', 'content.replyLength', 'content.missingReplyCharacters', 'content.minimumPostLength') }); // not sure if this is the right way, keeping here for now, we could use a mixin perhaps diff --git a/test/javascripts/fixtures/site_settings_fixtures.js b/test/javascripts/fixtures/site_settings_fixtures.js index b6cb910767b..d107cb38772 100644 --- a/test/javascripts/fixtures/site_settings_fixtures.js +++ b/test/javascripts/fixtures/site_settings_fixtures.js @@ -1,2 +1,2 @@ /*jshint maxlen:10000000 */ -Discourse.SiteSettings = {"title":"Discourse Meta","logo_url":"/assets/logo.png","logo_small_url":"/assets/logo-single.png","traditional_markdown_linebreaks":false,"top_menu":"latest|new|unread|read|favorited|categories","post_menu":"like|edit|flag|delete|share|bookmark|reply","share_links":"twitter|facebook|google+|email","track_external_right_clicks":false,"must_approve_users":false,"ga_tracking_code":"UA-33736483-2","ga_domain_name":"","enable_long_polling":true,"polling_interval":3000,"anon_polling_interval":30000,"min_post_length":20,"max_post_length":16000,"min_topic_title_length":15,"max_topic_title_length":255,"min_private_message_title_length":2,"allow_uncategorized_topics":true,"min_search_term_length":3,"flush_timings_secs":5,"supress_reply_directly_below":true,"email_domains_blacklist":"mailinator.com","email_domains_whitelist":null,"version_checks":true,"min_title_similar_length":10,"min_body_similar_length":15,"category_colors":"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890","max_upload_size_kb":1024,"category_featured_topics":6,"favicon_url":"/assets/favicon.ico","dynamic_favicon":false,"uncategorized_name":"uncategorized","uncategorized_color":"AB9364","uncategorized_text_color":"FFFFFF","invite_only":false,"login_required":false,"enable_local_logins":true,"enable_local_account_create":true,"enable_google_logins":true,"enable_yahoo_logins":true,"enable_twitter_logins":true,"enable_facebook_logins":true,"enable_cas_logins":false,"enable_github_logins":true,"enable_persona_logins":true,"educate_until_posts":2,"topic_views_heat_low":1000,"topic_views_heat_medium":2000,"topic_views_heat_high":5000}; \ No newline at end of file +Discourse.SiteSettings = {"title":"Discourse Meta","logo_url":"/assets/logo.png","logo_small_url":"/assets/logo-single.png","traditional_markdown_linebreaks":false,"top_menu":"latest|new|unread|read|favorited|categories","post_menu":"like|edit|flag|delete|share|bookmark|reply","share_links":"twitter|facebook|google+|email","track_external_right_clicks":false,"must_approve_users":false,"ga_tracking_code":"UA-33736483-2","ga_domain_name":"","enable_long_polling":true,"polling_interval":3000,"anon_polling_interval":30000,"min_post_length":20,"max_post_length":16000,"min_topic_title_length":15,"max_topic_title_length":255,"min_private_message_title_length":2,"allow_uncategorized_topics":true,"min_search_term_length":3,"flush_timings_secs":5,"supress_reply_directly_below":true,"email_domains_blacklist":"mailinator.com","email_domains_whitelist":null,"version_checks":true,"min_title_similar_length":10,"min_body_similar_length":15,"category_colors":"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890","max_upload_size_kb":1024,"category_featured_topics":6,"favicon_url":"/assets/favicon.ico","dynamic_favicon":false,"uncategorized_name":"uncategorized","uncategorized_color":"AB9364","uncategorized_text_color":"FFFFFF","invite_only":false,"login_required":false,"enable_local_logins":true,"enable_local_account_create":true,"enable_google_logins":true,"enable_yahoo_logins":true,"enable_twitter_logins":true,"enable_facebook_logins":true,"enable_cas_logins":false,"enable_github_logins":true,"enable_persona_logins":true,"educate_until_posts":2,"topic_views_heat_low":1000,"topic_views_heat_medium":2000,"topic_views_heat_high":5000,"min_private_message_post_length":5}; \ No newline at end of file diff --git a/test/javascripts/models/composer_test.js b/test/javascripts/models/composer_test.js index 0987ecad704..4cf15fac0be 100644 --- a/test/javascripts/models/composer_test.js +++ b/test/javascripts/models/composer_test.js @@ -16,4 +16,25 @@ test('replyLength', function() { replyLength("1[quote=]not counted[/quote]2[quote=]at all[/quote]3", 3, "removes quotes"); replyLength("1[quote=]not[quote=]counted[/quote]yay[/quote]2", 2, "handles nested quotes correctly"); -}) +}); + + +test('missingReplyCharacters', function() { + var missingReplyCharacters = function(val, isPM, expected, message) { + var composer = Discourse.Composer.create({ reply: val, creatingPrivateMessage: isPM }); + equal(composer.get('missingReplyCharacters'), expected, message); + } + + missingReplyCharacters('hi', false, Discourse.SiteSettings.min_post_length - 2, 'too short public post'); + missingReplyCharacters('hi', true, Discourse.SiteSettings.min_private_message_post_length - 2, 'too short private message'); +}); + +test('missingTitleCharacters', function() { + var missingTitleCharacters = function(val, isPM, expected, message) { + var composer = Discourse.Composer.create({ title: val, creatingPrivateMessage: isPM }); + equal(composer.get('missingTitleCharacters'), expected, message); + } + + missingTitleCharacters('hi', false, Discourse.SiteSettings.min_topic_title_length - 2, 'too short post title'); + missingTitleCharacters('z', true, Discourse.SiteSettings.min_private_message_title_length - 1, 'too short pm title'); +}); \ No newline at end of file