Merge pull request #651 from ZogStriP/change-title-background-when-composer-requirements-are-not-met

Change Title background to red when requirements are not met
This commit is contained in:
Sam 2013-04-07 15:11:10 -07:00
commit 3ba0bf6d5d
7 changed files with 104 additions and 76 deletions

View File

@ -18,8 +18,8 @@ Discourse.ComposerController = Discourse.Controller.extend({
this.get('content').importQuote(); this.get('content').importQuote();
}, },
resetDraftStatus: function() { updateDraftStatus: function() {
this.get('content').resetDraftStatus(); this.get('content').updateDraftStatus();
}, },
appendText: function(text) { appendText: function(text) {

View File

@ -31,43 +31,43 @@ Discourse.Composer = Discourse.Model.extend({
this.set('archetypeId', Discourse.get('site.default_archetype')); this.set('archetypeId', Discourse.get('site.default_archetype'));
}, },
creatingTopic: (function() { creatingTopic: function() {
return this.get('action') === CREATE_TOPIC; return this.get('action') === CREATE_TOPIC;
}).property('action'), }.property('action'),
creatingPrivateMessage: (function() { creatingPrivateMessage: function() {
return this.get('action') === PRIVATE_MESSAGE; return this.get('action') === PRIVATE_MESSAGE;
}).property('action'), }.property('action'),
editingPost: (function() { editingPost: function() {
return this.get('action') === EDIT; return this.get('action') === EDIT;
}).property('action'), }.property('action'),
replyingToTopic: (function() { replyingToTopic: function() {
return this.get('action') === REPLY; return this.get('action') === REPLY;
}).property('action'), }.property('action'),
viewOpen: (function() { viewOpen: function() {
return this.get('composeState') === OPEN; return this.get('composeState') === OPEN;
}).property('composeState'), }.property('composeState'),
archetype: (function() { archetype: function() {
return this.get('archetypes').findProperty('id', this.get('archetypeId')); return this.get('archetypes').findProperty('id', this.get('archetypeId'));
}).property('archetypeId'), }.property('archetypeId'),
archetypeChanged: (function() { archetypeChanged: function() {
return this.set('metaData', Em.Object.create()); return this.set('metaData', Em.Object.create());
}).observes('archetype'), }.observes('archetype'),
editTitle: (function() { editTitle: function() {
if (this.get('creatingTopic') || this.get('creatingPrivateMessage')) return true; if (this.get('creatingTopic') || this.get('creatingPrivateMessage')) return true;
if (this.get('editingPost') && this.get('post.post_number') === 1) return true; if (this.get('editingPost') && this.get('post.post_number') === 1) return true;
return false; return false;
}).property('editingPost', 'creatingTopic', 'post.post_number'), }.property('editingPost', 'creatingTopic', 'post.post_number'),
togglePreview: function() { togglePreview: function() {
this.toggleProperty('showPreview'); this.toggleProperty('showPreview');
return Discourse.KeyValueStore.set({ key: 'showPreview', value: this.get('showPreview') }); Discourse.KeyValueStore.set({ key: 'showPreview', value: this.get('showPreview') });
}, },
// Import a quote from the post // Import a quote from the post
@ -97,7 +97,7 @@ Discourse.Composer = Discourse.Model.extend({
}, },
// Determine the appropriate title for this action // Determine the appropriate title for this action
actionTitle: (function() { actionTitle: function() {
var topic = this.get('topic'); var topic = this.get('topic');
var postLink, topicLink; var postLink, topicLink;
@ -128,28 +128,26 @@ Discourse.Composer = Discourse.Model.extend({
} }
switch (this.get('action')) { switch (this.get('action')) {
case PRIVATE_MESSAGE: case PRIVATE_MESSAGE: return Em.String.i18n('topic.private_message');
return Em.String.i18n('topic.private_message'); case CREATE_TOPIC: return Em.String.i18n('topic.create_long');
case CREATE_TOPIC:
return Em.String.i18n('topic.create_long');
case REPLY: case REPLY:
case EDIT: case EDIT:
if (postDescription) return postDescription; if (postDescription) return postDescription;
if (topic) return Em.String.i18n('post.reply_topic', { link: topicLink }); if (topic) return Em.String.i18n('post.reply_topic', { link: topicLink });
} }
}).property('action', 'post', 'topic', 'topic.title'), }.property('action', 'post', 'topic', 'topic.title'),
toggleText: (function() { toggleText: function() {
return this.get('showPreview') ? Em.String.i18n('composer.hide_preview') : Em.String.i18n('composer.show_preview'); return this.get('showPreview') ? Em.String.i18n('composer.hide_preview') : Em.String.i18n('composer.show_preview');
}).property('showPreview'), }.property('showPreview'),
hidePreview: (function() { hidePreview: function() {
return !this.get('showPreview'); return !this.get('showPreview');
}).property('showPreview'), }.property('showPreview'),
// Whether to disable the post button // Whether to disable the post button
cantSubmitPost: (function() { cantSubmitPost: function() {
// Can't submit while loading // Can't submit while loading
if (this.get('loading')) return true; if (this.get('loading')) return true;
@ -167,29 +165,22 @@ Discourse.Composer = Discourse.Model.extend({
if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return true; if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return true;
return false; return false;
}).property('loading', 'editTitle', 'titleLength', 'targetUsernames', 'replyLength'), }.property('loading', 'editTitle', 'titleLength', 'targetUsernames', 'replyLength'),
// The text for the save button // The text for the save button
saveText: (function() { saveText: function() {
switch (this.get('action')) { switch (this.get('action')) {
case EDIT: case EDIT: return Em.String.i18n('composer.save_edit');
return Em.String.i18n('composer.save_edit'); case REPLY: return Em.String.i18n('composer.reply');
case REPLY: case CREATE_TOPIC: return Em.String.i18n('composer.create_topic');
return Em.String.i18n('composer.reply'); case PRIVATE_MESSAGE: return Em.String.i18n('composer.create_pm');
case CREATE_TOPIC:
return Em.String.i18n('composer.create_topic');
case PRIVATE_MESSAGE:
return Em.String.i18n('composer.create_pm');
} }
}).property('action'), }.property('action'),
hasMetaData: (function() { hasMetaData: function() {
var metaData = this.get('metaData'); var metaData = this.get('metaData');
if (!this.get('metaData')) { return metaData ? Em.empty(Em.keys(this.get('metaData'))) : false;
return false; }.property('metaData'),
}
return Em.empty(Em.keys(this.get('metaData')));
}).property('metaData'),
wouldLoseChanges: function() { wouldLoseChanges: function() {
return this.get('reply') !== this.get('originalText'); return this.get('reply') !== this.get('originalText');
@ -277,8 +268,7 @@ Discourse.Composer = Discourse.Model.extend({
}, },
save: function(opts) { save: function(opts) {
if (this.get('editingPost')) return this.editPost(opts); return this.get('editingPost') ? this.editPost(opts) : this.createPost(opts);
return this.createPost(opts);
}, },
// When you edit a post // When you edit a post
@ -458,31 +448,57 @@ Discourse.Composer = Discourse.Model.extend({
this.set('draftStatus', Em.String.i18n('composer.saving_draft_tip')); this.set('draftStatus', Em.String.i18n('composer.saving_draft_tip'));
var composer = this; var composer = this;
return Discourse.Draft.save(this.get('draftKey'), this.get('draftSequence'), data).then((function() {
// try to save the draft
return Discourse.Draft.save(this.get('draftKey'), this.get('draftSequence'), data)
.then(function() {
composer.set('draftStatus', Em.String.i18n('composer.saved_draft_tip')); composer.set('draftStatus', Em.String.i18n('composer.saved_draft_tip'));
}), (function() { }, function() {
composer.set('draftStatus', Em.String.i18n('composer.drafts_offline')); composer.set('draftStatus', Em.String.i18n('composer.drafts_offline'));
})); });
}, },
resetDraftStatus: (function() { updateDraftStatus: function() {
var $title = $('#reply-title'),
$reply = $('#wmd-input');
// 'title' is focused // 'title' is focused
if ($('#reply-title').is(':focus')) { if ($title.is(':focus')) {
var titleDiff = Discourse.SiteSettings.min_topic_title_length - this.get('titleLength'); var titleDiff = this.get('missingTitleCharacters');
if (titleDiff > 0) { if (titleDiff > 0) {
return this.set('draftStatus', Em.String.i18n('composer.min_length.need_more_for_title', { n: titleDiff })); return this.set('draftStatus', Em.String.i18n('composer.min_length.need_more_for_title', { n: titleDiff }));
} }
// 'reply' is focused // 'reply' is focused
} else if ($('#wmd-input').is(':focus')) { } else if ($reply.is(':focus')) {
var replyDiff = Discourse.SiteSettings.min_post_length - this.get('replyLength'); var replyDiff = this.get('missingReplyCharacters');
if (replyDiff > 0) { if (replyDiff > 0) {
return this.set('draftStatus', Em.String.i18n('composer.min_length.need_more_for_reply', { n: replyDiff })); 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 // hide the counters if the currently focused text field is OK
this.set('draftStatus', null); this.set('draftStatus', null);
}).observes('replyLength', 'titleLength'), }.observes('missingTitleCharacters', 'missingReplyCharacters'),
/**
Number of missing characters in the title until valid.
@property missingTitleCharacters
**/
missingTitleCharacters: function() {
return Discourse.SiteSettings.min_topic_title_length - this.get('titleLength');
}.property('titleLength'),
/**
Number of missing characters in the reply until valid.
@property missingReplyCharacters
**/
missingReplyCharacters: function() {
return Discourse.SiteSettings.min_post_length - this.get('replyLength');
}.property('replyLength'),
/** /**
Computes the length of the title minus non-significant whitespaces Computes the length of the title minus non-significant whitespaces

View File

@ -50,8 +50,6 @@ Discourse.TopicList = Discourse.Model.extend({
unseen: true, unseen: true,
highlight: true highlight: true
}); });
console.log(newTopic);
this.get('inserted').unshiftObject(newTopic); this.get('inserted').unshiftObject(newTopic);
} }

View File

@ -17,10 +17,7 @@ Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
}, },
setupController: function(controller) { setupController: function(controller) {
console.log('prefereces');
controller.set('content', this.controllerFor('user').get('content')); controller.set('content', this.controllerFor('user').get('content'));
} }
}); });

View File

@ -50,7 +50,7 @@
</div> </div>
{{#if Discourse.currentUser}} {{#if Discourse.currentUser}}
<a href="#" {{action togglePreview target="controller"}} class='toggle-preview'>{{{content.toggleText}}}</a> <a href="#" {{action togglePreview target="controller"}} class='toggle-preview'>{{{content.toggleText}}}</a>
<div class='saving-draft'></div> <div class='draft-status'></div>
{{#if view.loadingImage}} {{#if view.loadingImage}}
<div id="image-uploading"> <div id="image-uploading">
{{i18n image_selector.uploading_image}} {{view.uploadProgress}}% <a id="cancel-image-upload">{{i18n cancel}}</a> {{i18n image_selector.uploading_image}} {{view.uploadProgress}}% <a id="cancel-image-upload">{{i18n cancel}}</a>

View File

@ -27,7 +27,7 @@ Discourse.ComposerView = Discourse.View.extend({
}.property('content.composeState'), }.property('content.composeState'),
draftStatus: function() { draftStatus: function() {
this.$('.saving-draft').text(this.get('content.draftStatus') || ""); this.$('.draft-status').text(this.get('content.draftStatus') || "");
}.observes('content.draftStatus'), }.observes('content.draftStatus'),
// Disable fields when we're loading // Disable fields when we're loading
@ -40,8 +40,7 @@ Discourse.ComposerView = Discourse.View.extend({
}.observes('loading'), }.observes('loading'),
postMade: function() { postMade: function() {
if (this.present('controller.createdPost')) return 'created-post'; return this.present('controller.createdPost') ? 'created-post' : null;
return null;
}.property('content.createdPost'), }.property('content.createdPost'),
observeReplyChanges: function() { observeReplyChanges: function() {
@ -87,7 +86,7 @@ Discourse.ComposerView = Discourse.View.extend({
focusIn: function() { focusIn: function() {
var controller = this.get('controller'); var controller = this.get('controller');
if(controller) controller.resetDraftStatus(); if (controller) controller.updateDraftStatus();
}, },
resize: function() { resize: function() {
@ -123,9 +122,9 @@ Discourse.ComposerView = Discourse.View.extend({
}, },
didInsertElement: function() { didInsertElement: function() {
var replyControl = $('#reply-control'); var $replyControl = $('#reply-control');
replyControl.DivResizer({ resize: this.resize, onDrag: this.movePanels }); $replyControl.DivResizer({ resize: this.resize, onDrag: this.movePanels });
Discourse.TransitionHelper.after(replyControl, this.resize); Discourse.TransitionHelper.after($replyControl, this.resize);
}, },
click: function() { click: function() {
@ -260,11 +259,26 @@ Discourse.ComposerView = Discourse.View.extend({
return true; return true;
}); });
$('#reply-title').keyup(function() { var $replyTitle = $('#reply-title');
$replyTitle.keyup(function() {
saveDraft(); saveDraft();
// removes the red background once the requirements are met
if (_this.get('controller.content.missingTitleCharacters') <= 0) {
$replyTitle.removeClass("requirements-not-met");
}
return true; return true;
}); });
// when the title field loses the focus...
$replyTitle.blur(function(){
// ...and the requirements are not met (ie. the minimum number of characters)
if (_this.get('controller.content.missingTitleCharacters') > 0) {
// then, "redify" the background
$replyTitle.toggleClass("requirements-not-met", true);
}
});
// In case it's still bound somehow // In case it's still bound somehow
$uploadTarget.fileupload('destroy'); $uploadTarget.fileupload('destroy');
$uploadTarget.off(); $uploadTarget.off();

View File

@ -55,7 +55,10 @@
} }
#reply-control { #reply-control {
.toggle-preview, .saving-draft, #image-uploading { .requirements-not-met {
background-color: rgba(255, 0, 0, 0.12);
}
.toggle-preview, .draft-status, #image-uploading {
position: absolute; position: absolute;
bottom: -31px; bottom: -31px;
margin-top: 0px; margin-top: 0px;
@ -69,7 +72,7 @@
font-size: 12px; font-size: 12px;
color: darken($gray, 40); color: darken($gray, 40);
} }
.saving-draft { .draft-status {
right: 51%; right: 51%;
color: lighten($black, 60); color: lighten($black, 60);
} }