FEATURE: when uncategorized topics are not allowed, disable the post input until a category is chosen

This commit is contained in:
Neil Lalonde
2018-04-10 19:31:20 -04:00
parent 720dd2432e
commit 6e6892c88e
9 changed files with 107 additions and 12 deletions

View File

@ -37,10 +37,19 @@ export default Ember.Component.extend({
return `[${I18n.t('uploading')}]() `; return `[${I18n.t('uploading')}]() `;
}, },
@computed() @computed('composer.requiredCategoryMissing')
replyPlaceholder() { replyPlaceholder(requiredCategoryMissing) {
if (requiredCategoryMissing) {
return 'composer.reply_placeholder_choose_category';
} else {
const key = authorizesOneOrMoreImageExtensions() ? "reply_placeholder" : "reply_placeholder_no_images"; const key = authorizesOneOrMoreImageExtensions() ? "reply_placeholder" : "reply_placeholder_no_images";
return `composer.${key}`; return `composer.${key}`;
}
},
@computed('composer.requiredCategoryMissing', 'composer.replyLength')
disableTextarea(requiredCategoryMissing, replyLength) {
return requiredCategoryMissing && replyLength === 0;
}, },
@observes('composer.uploadCancelled') @observes('composer.uploadCancelled')

View File

@ -750,6 +750,8 @@ export default Ember.Component.extend({
}, },
toolbarButton(button) { toolbarButton(button) {
if (this.get('disabled')) { return; }
const selected = this._getSelected(button.trimLeading); const selected = this._getSelected(button.trimLeading);
const toolbarEvent = { const toolbarEvent = {
selected, selected,
@ -770,6 +772,8 @@ export default Ember.Component.extend({
}, },
showLinkModal() { showLinkModal() {
if (this.get('disabled')) { return; }
this._lastSel = this._getSelected(); this._lastSel = this._getSelected();
if (this._lastSel) { if (this._lastSel) {
@ -780,6 +784,8 @@ export default Ember.Component.extend({
}, },
formatCode() { formatCode() {
if (this.get('disabled')) { return; }
const sel = this._getSelected('', { lineVal: true }); const sel = this._getSelected('', { lineVal: true });
const selValue = sel.value; const selValue = sel.value;
const hasNewLine = selValue.indexOf("\n") !== -1; const hasNewLine = selValue.indexOf("\n") !== -1;
@ -833,6 +839,7 @@ export default Ember.Component.extend({
}, },
emoji() { emoji() {
if (this.get('disabled')) { return; }
this.set('emojiPickerIsActive', !this.get('emojiPickerIsActive')); this.set('emojiPickerIsActive', !this.get('emojiPickerIsActive'));
} }
} }

View File

@ -265,13 +265,17 @@ const Composer = RestModel.extend({
return this.get('targetUsernames') && (this.get('targetUsernames').trim() + ',').indexOf(',') === 0; return this.get('targetUsernames') && (this.get('targetUsernames').trim() + ',').indexOf(',') === 0;
} else { } else {
// has a category? (when needed) // has a category? (when needed)
return this.get('canCategorize') && return this.get('requiredCategoryMissing');
!this.siteSettings.allow_uncategorized_topics &&
!this.get('categoryId') &&
!this.user.get('admin');
} }
}.property('loading', 'canEditTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryId', 'missingReplyCharacters'), }.property('loading', 'canEditTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryId', 'missingReplyCharacters'),
@computed('canCategorize', 'categoryId')
requiredCategoryMissing(canCategorize, categoryId) {
return canCategorize && !categoryId &&
!this.siteSettings.allow_uncategorized_topics &&
!this.user.get('admin');
},
titleLengthValid: function() { titleLengthValid: function() {
if (this.user.get('admin') && this.get('post.static_doc') && this.get('titleLength') > 0) return true; if (this.user.get('admin') && this.get('post.static_doc') && this.get('titleLength') > 0) return true;
if (this.get('titleLength') < this.get('minimumTitleLength')) return false; if (this.get('titleLength') < this.get('minimumTitleLength')) return false;

View File

@ -16,6 +16,7 @@
onExpandPopupMenuOptions="onExpandPopupMenuOptions" onExpandPopupMenuOptions="onExpandPopupMenuOptions"
onPopupMenuAction=onPopupMenuAction onPopupMenuAction=onPopupMenuAction
popupMenuOptions=popupMenuOptions popupMenuOptions=popupMenuOptions
disabled=disableTextarea
outletArgs=(hash composer=composer editorType="composer")}} outletArgs=(hash composer=composer editorType="composer")}}
{{#if site.mobileView}} {{#if site.mobileView}}

View File

@ -10,7 +10,7 @@
<div class='d-editor-container'> <div class='d-editor-container'>
<div class="d-editor-textarea-wrapper"> <div class="d-editor-textarea-wrapper">
<div class='d-editor-button-bar'> <div class='d-editor-button-bar {{if disabled "disabled"}}'>
{{#each toolbar.groups as |group|}} {{#each toolbar.groups as |group|}}
{{#each group.buttons as |b|}} {{#each group.buttons as |b|}}
{{#if b.popupMenu}} {{#if b.popupMenu}}
@ -39,7 +39,7 @@
</div> </div>
{{conditional-loading-spinner condition=loading}} {{conditional-loading-spinner condition=loading}}
{{textarea tabindex=tabindex value=value class="d-editor-input" placeholder=placeholderTranslated}} {{textarea tabindex=tabindex value=value class="d-editor-input" placeholder=placeholderTranslated disabled=disabled}}
{{popup-input-tip validation=validation}} {{popup-input-tip validation=validation}}
{{plugin-outlet name="after-d-editor" tagName="" args=outletArgs}} {{plugin-outlet name="after-d-editor" tagName="" args=outletArgs}}
</div> </div>

View File

@ -90,6 +90,11 @@
.btn.italic { .btn.italic {
font-style: italic; font-style: italic;
} }
&.disabled {
visibility: hidden;
cursor: not-allowed;
}
} }
.d-editor-spacer { .d-editor-spacer {

View File

@ -1325,6 +1325,7 @@ en:
remove_featured_link: "Remove link from topic." remove_featured_link: "Remove link from topic."
reply_placeholder: "Type here. Use Markdown, BBCode, or HTML to format. Drag or paste images." reply_placeholder: "Type here. Use Markdown, BBCode, or HTML to format. Drag or paste images."
reply_placeholder_no_images: "Type here. Use Markdown, BBCode, or HTML to format." reply_placeholder_no_images: "Type here. Use Markdown, BBCode, or HTML to format."
reply_placeholder_choose_category: "Please select a category."
view_new_post: "View your new post." view_new_post: "View your new post."
saving: "Saving" saving: "Saving"
saved: "Saved!" saved: "Saved!"

View File

@ -1,4 +1,4 @@
import { acceptance } from "helpers/qunit-helpers"; import { acceptance, replaceCurrentUser } from "helpers/qunit-helpers";
acceptance("Composer", { acceptance("Composer", {
loggedIn: true, loggedIn: true,
@ -335,3 +335,42 @@ QUnit.test("Composer draft with dirty reply can toggle to edit", assert => {
assert.equal(find('.d-editor-input').val().indexOf('This is the first post.'), 0, 'it populates the input with the post text'); assert.equal(find('.d-editor-input').val().indexOf('This is the first post.'), 0, 'it populates the input with the post text');
}); });
}); });
acceptance("Composer and uncategorized is not allowed", {
loggedIn: true,
settings: {
enable_whispers: true,
allow_uncategorized_topics: false
}
});
QUnit.test("Disable body until category is selected", assert => {
replaceCurrentUser({ admin: false, staff: false, trust_level: 1 });
visit("/");
click('#create-topic');
andThen(() => {
assert.ok(exists('.d-editor-input'), 'the composer input is visible');
assert.ok(exists('.title-input .popup-tip.bad.hide'), 'title errors are hidden by default');
assert.ok(exists('.d-editor-textarea-wrapper .popup-tip.bad.hide'), 'body errors are hidden by default');
assert.ok(exists('.d-editor-container .d-editor-button-bar.disabled'), 'toolbar is disabled');
assert.ok(find('.d-editor-container .d-editor-input:disabled').length, 'textarea is disabled');
});
const categoryChooser = selectKit('.category-chooser');
categoryChooser.expand().selectRowByValue(2);
andThen(() => {
assert.ok(!exists('.d-editor-container .d-editor-button-bar.disabled'), 'toolbar is enabled');
assert.ok(find('.d-editor-container .d-editor-input:disabled').length === 0, 'textarea is enabled');
});
fillIn('.d-editor-input', 'Now I can type stuff');
categoryChooser.expand().selectRowByValue('__none__');
andThen(() => {
assert.ok(!exists('.d-editor-container .d-editor-button-bar.disabled'), 'toolbar is still enabled');
assert.ok(find('.d-editor-container .d-editor-input:disabled').length === 0, 'textarea is still enabled');
});
});

View File

@ -1,4 +1,4 @@
import { acceptance } from "helpers/qunit-helpers"; import { acceptance, replaceCurrentUser } from "helpers/qunit-helpers";
acceptance("Composer topic featured links", { acceptance("Composer topic featured links", {
loggedIn: true, loggedIn: true,
@ -76,3 +76,32 @@ QUnit.test("onebox with title but extra words in title field", assert => {
assert.equal(find('.title-input input').val(), "http://www.example.com/has-title.html test", "title is unchanged"); assert.equal(find('.title-input input').val(), "http://www.example.com/has-title.html test", "title is unchanged");
}); });
}); });
acceptance("Composer topic featured links when uncategorized is not allowed", {
loggedIn: true,
settings: {
topic_featured_link_enabled: true,
max_topic_title_length: 80,
enable_markdown_linkify: true,
allow_uncategorized_topics: false
}
});
QUnit.test("Pasting a link enables the text input area", assert => {
replaceCurrentUser({ admin: false, staff: false, trust_level: 1 });
visit("/");
click('#create-topic');
andThen(() => {
assert.ok(exists('.d-editor-container .d-editor-button-bar.disabled'), 'toolbar is disabled');
assert.ok(find('.d-editor-container .d-editor-input:disabled').length, 'textarea is disabled');
});
fillIn('#reply-title', "http://www.example.com/has-title.html");
andThen(() => {
assert.ok(find('.d-editor-preview').html().trim().indexOf('onebox') > 0, "it pastes the link into the body and previews it");
assert.ok(exists('.d-editor-textarea-wrapper .popup-tip.good'), 'the body is now good');
assert.equal(find('.title-input input').val(), "An interesting article", "title is from the oneboxed article");
assert.ok(!exists('.d-editor-container .d-editor-button-bar.disabled'), 'toolbar is enabled');
assert.ok(find('.d-editor-container .d-editor-input:disabled').length === 0, 'textarea is enabled');
});
});