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}}",