diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index 1a6bf47dd0f..009fd35a8dd 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -297,6 +297,12 @@ export default Ember.Controller.extend({ uploadIcon: () => uploadIcon(), actions: { + resetTagsSelection() { + if (this.get("model.tags")) { + this.set("model.tags", []); + } + }, + cancelUpload() { this.set("model.uploadCancelled", true); }, diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 index 7f3b9e43898..e544c80ed94 100644 --- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 +++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 @@ -38,7 +38,7 @@ import Sharing from "discourse/lib/sharing"; import { addComposerUploadHandler } from "discourse/components/composer-editor"; // If you add any methods to the API ensure you bump up this number -const PLUGIN_API_VERSION = "0.8.24"; +const PLUGIN_API_VERSION = "0.8.25"; class PluginApi { constructor(version, container) { diff --git a/app/assets/javascripts/discourse/templates/composer.hbs b/app/assets/javascripts/discourse/templates/composer.hbs index 94e8d44b643..7c75f0ba03a 100644 --- a/app/assets/javascripts/discourse/templates/composer.hbs +++ b/app/assets/javascripts/discourse/templates/composer.hbs @@ -60,7 +60,13 @@ {{#if model.showCategoryChooser}}
- {{category-chooser fullWidthOnMobile=true value=model.categoryId scopedCategoryId=scopedCategoryId tabindex="3"}} + {{category-chooser + fullWidthOnMobile=true + value=model.categoryId + scopedCategoryId=scopedCategoryId + onSelect=(action "resetTagsSelection") + onSelectNone=(action "resetTagsSelection") + tabindex="3"}} {{popup-input-tip validation=categoryValidation}}
{{/if}} diff --git a/app/assets/javascripts/select-kit/components/multi-select.js.es6 b/app/assets/javascripts/select-kit/components/multi-select.js.es6 index 86d8fcd22ae..b2a71ebf88c 100644 --- a/app/assets/javascripts/select-kit/components/multi-select.js.es6 +++ b/app/assets/javascripts/select-kit/components/multi-select.js.es6 @@ -2,7 +2,10 @@ import SelectKitComponent from "select-kit/components/select-kit"; import computed from "ember-addons/ember-computed-decorators"; import { on } from "ember-addons/ember-computed-decorators"; const { get, isNone, isEmpty, makeArray, run } = Ember; -import { applyOnSelectPluginApiCallbacks } from "select-kit/mixins/plugin-api"; +import { + applyOnSelectPluginApiCallbacks, + applyOnSelectNonePluginApiCallbacks +} from "select-kit/mixins/plugin-api"; export default SelectKitComponent.extend({ pluginApiIdentifiers: ["multi-select"], @@ -253,6 +256,11 @@ export default SelectKitComponent.extend({ !computedContentItem || computedContentItem.__sk_row_type === "noneRow" ) { + applyOnSelectNonePluginApiCallbacks( + this.get("pluginApiIdentifiers"), + this + ); + this._boundaryActionHandler("onSelectNone"); this.clearSelection(); return; } diff --git a/app/assets/javascripts/select-kit/components/single-select.js.es6 b/app/assets/javascripts/select-kit/components/single-select.js.es6 index 8be8102fce6..7713d51194b 100644 --- a/app/assets/javascripts/select-kit/components/single-select.js.es6 +++ b/app/assets/javascripts/select-kit/components/single-select.js.es6 @@ -5,7 +5,10 @@ import { } from "ember-addons/ember-computed-decorators"; const { get, isNone, isEmpty, isPresent, run, makeArray } = Ember; -import { applyOnSelectPluginApiCallbacks } from "select-kit/mixins/plugin-api"; +import { + applyOnSelectPluginApiCallbacks, + applyOnSelectNonePluginApiCallbacks +} from "select-kit/mixins/plugin-api"; export default SelectKitComponent.extend({ pluginApiIdentifiers: ["single-select"], @@ -211,6 +214,11 @@ export default SelectKitComponent.extend({ !computedContentItem || computedContentItem.__sk_row_type === "noneRow" ) { + applyOnSelectNonePluginApiCallbacks( + this.get("pluginApiIdentifiers"), + this + ); + this._boundaryActionHandler("onSelectNone"); this.clearSelection(); return; } diff --git a/app/assets/javascripts/select-kit/mixins/plugin-api.js.es6 b/app/assets/javascripts/select-kit/mixins/plugin-api.js.es6 index b34f88c51ae..daa1e362a7d 100644 --- a/app/assets/javascripts/select-kit/mixins/plugin-api.js.es6 +++ b/app/assets/javascripts/select-kit/mixins/plugin-api.js.es6 @@ -47,6 +47,15 @@ function modifyCollectionHeader(pluginApiIdentifiers, contentFunction) { _modifyCollectionHeaderCallbacks[pluginApiIdentifiers].push(contentFunction); } +let _onSelectNoneCallbacks = {}; +function onSelectNone(pluginApiIdentifiers, mutationFunction) { + if (Ember.isNone(_onSelectNoneCallbacks[pluginApiIdentifiers])) { + _onSelectNoneCallbacks[pluginApiIdentifiers] = []; + } + + _onSelectNoneCallbacks[pluginApiIdentifiers].push(mutationFunction); +} + let _onSelectCallbacks = {}; function onSelect(pluginApiIdentifiers, mutationFunction) { if (Ember.isNone(_onSelectCallbacks[pluginApiIdentifiers])) { @@ -102,6 +111,12 @@ export function applyOnSelectPluginApiCallbacks(identifiers, val, context) { }); } +export function applyOnSelectNonePluginApiCallbacks(identifiers, context) { + identifiers.forEach(key => { + (_onSelectNoneCallbacks[key] || []).forEach(c => c(context)); + }); +} + export function modifySelectKit(pluginApiIdentifiers) { return { appendContent: content => { @@ -131,6 +146,10 @@ export function modifySelectKit(pluginApiIdentifiers) { onSelect: callback => { onSelect(pluginApiIdentifiers, callback); return modifySelectKit(pluginApiIdentifiers); + }, + onSelectNone: callback => { + onSelectNone(pluginApiIdentifiers, callback); + return modifySelectKit(pluginApiIdentifiers); } }; } @@ -142,6 +161,7 @@ export function clearCallbacks() { _modifyHeaderComputedContentCallbacks = {}; _modifyCollectionHeaderCallbacks = {}; _onSelectCallbacks = {}; + _onSelectNoneCallbacks = {}; } const EMPTY_ARRAY = Object.freeze([]); diff --git a/test/javascripts/acceptance/category-chooser-with-tags-test.js.es6 b/test/javascripts/acceptance/category-chooser-with-tags-test.js.es6 new file mode 100644 index 00000000000..234eb2d8565 --- /dev/null +++ b/test/javascripts/acceptance/category-chooser-with-tags-test.js.es6 @@ -0,0 +1,39 @@ +import { acceptance } from "helpers/qunit-helpers"; + +acceptance("CategoryChooser - with tags", { + loggedIn: true, + site: { can_tag_topics: true }, + settings: { + tagging_enabled: true, + allow_uncategorized_topics: false + } +}); + +QUnit.test("resets tags when changing category", async assert => { + const categoryChooser = selectKit(".category-chooser"); + const miniTagChooser = selectKit(".mini-tag-chooser"); + const findSelected = () => + find(".mini-tag-chooser .mini-tag-chooser-header .selected-name").text(); + + await visit("/"); + await click("#create-topic"); + await miniTagChooser.expand(); + await miniTagChooser.selectRowByValue("monkey"); + + assert.equal(findSelected(), "monkey"); + + await categoryChooser.expand(); + await categoryChooser.selectRowByValue(6); + + assert.equal(findSelected(), "optional tags"); + + await miniTagChooser.expand(); + await miniTagChooser.selectRowByValue("monkey"); + + assert.equal(findSelected(), "monkey"); + + await categoryChooser.expand(); + await categoryChooser.selectNoneRow(); + + assert.equal(findSelected(), "optional tags"); +}); diff --git a/test/javascripts/components/single-select-test.js.es6 b/test/javascripts/components/single-select-test.js.es6 index 056c963400f..7e6c6158a40 100644 --- a/test/javascripts/components/single-select-test.js.es6 +++ b/test/javascripts/components/single-select-test.js.es6 @@ -501,6 +501,32 @@ componentTest("support modifying on select behavior through plugin api", { } }); +componentTest("support modifying on select none behavior through plugin api", { + template: + '{{single-select none="none" content=content}}', + + beforeEach() { + withPluginApi("0.8.25", api => { + api.modifySelectKit("select-kit").onSelectNone(() => { + find(".on-select-none-test").html("NONE"); + }); + }); + + this.set("content", [{ id: "1", name: "robin" }]); + }, + + async test(assert) { + await this.get("subject").expand(); + await this.get("subject").selectRowByValue(1); + await this.get("subject").expand(); + await this.get("subject").selectNoneRow(); + + assert.equal(find(".on-select-none-test").html(), "NONE"); + + clearCallbacks(); + } +}); + componentTest("with nameChanges", { template: "{{single-select content=content nameChanges=true}}",