FIX: fixes few regressions in select-kit (#17453)

- following c3fd91670e `paste` has been typoed into `pase`
- adds two tests for pasting in `multi-select` and `email-group-user-chooser`
- selectKitOptions would not be following the right overriding order
- `category-selector` was using `selectKitOptions` directly which shouldn't be the case as it's not using computed values
- apparently since a recent ember upgrade, paste event is not providing `originalEvent` anymore and `clipboardData` should be retrieved directly on the event
This commit is contained in:
Joffrey JAFFEUX 2022-07-12 21:38:17 +02:00 committed by GitHub
parent 09f1ef6b05
commit a939609d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 107 additions and 20 deletions

View File

@ -0,0 +1,51 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import { paste, query } from "discourse/tests/helpers/qunit-helpers";
const DEFAULT_CONTENT = [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" },
];
const setDefaultState = (ctx, options) => {
const properties = Object.assign(
{
content: DEFAULT_CONTENT,
value: null,
},
options || {}
);
ctx.setProperties(properties);
};
module(
"Integration | Component | select-kit/email-group-user-chooser",
function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.set("subject", selectKit());
});
test("pasting", async function (assert) {
setDefaultState(this);
await render(hbs`
<EmailGroupUserChooser
@value={{this.value}}
@content={{this.content}}
@options={{hash maximum=2}}
/>
`);
await this.subject.expand();
await paste(query(".filter-input"), "foo,bar");
assert.equal(this.subject.header().value(), "foo,bar");
});
}
);

View File

@ -3,6 +3,7 @@ import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { render } from "@ember/test-helpers"; import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars"; import { hbs } from "ember-cli-htmlbars";
import selectKit from "discourse/tests/helpers/select-kit-helper"; import selectKit from "discourse/tests/helpers/select-kit-helper";
import { paste, query } from "discourse/tests/helpers/qunit-helpers";
const DEFAULT_CONTENT = [ const DEFAULT_CONTENT = [
{ id: 1, name: "foo" }, { id: 1, name: "foo" },
@ -100,4 +101,21 @@ module("Integration | Component | select-kit/multi-select", function (hooks) {
assert.ok(this.subject.isExpanded(), "it doesnt close the dropdown"); assert.ok(this.subject.isExpanded(), "it doesnt close the dropdown");
}); });
test("pasting", async function (assert) {
setDefaultState(this);
await render(hbs`
<MultiSelect
@value={{this.value}}
@content={{this.content}}
@options={{hash maximum=2}}
/>
`);
await this.subject.expand();
await paste(query(".filter-input"), "foo|bar");
assert.equal(this.subject.header().value(), "1,2");
});
}); });

View File

@ -40,7 +40,7 @@ export default MultiSelectComponent.extend({
return this.attrs.options.allowUncategorized; return this.attrs.options.allowUncategorized;
} }
return this.selectKitOptions.allowUncategorized; return this.selectKit.options.allowUncategorized;
} }
return ( return (

View File

@ -10,7 +10,7 @@ export default MultiSelectFilterComponent.extend({
return; return;
} }
const data = event.originalEvent.clipboardData; const data = event?.clipboardData;
if (!data) { if (!data) {
return; return;

View File

@ -19,6 +19,7 @@ export default SelectKitComponent.extend({
closeOnChange: false, closeOnChange: false,
autoInsertNoneItem: false, autoInsertNoneItem: false,
headerComponent: "multi-select/multi-select-header", headerComponent: "multi-select/multi-select-header",
filterComponent: "multi-select/multi-select-filter",
autoFilterable: true, autoFilterable: true,
caretDownIcon: "caretIcon", caretDownIcon: "caretIcon",
caretUpIcon: "caretIcon", caretUpIcon: "caretIcon",

View File

@ -3,6 +3,7 @@ import SelectKitFilterComponent from "select-kit/components/select-kit/select-ki
import { isEmpty } from "@ember/utils"; import { isEmpty } from "@ember/utils";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import layout from "select-kit/templates/components/select-kit/select-kit-filter"; import layout from "select-kit/templates/components/select-kit/select-kit-filter";
import { action } from "@ember/object";
export default SelectKitFilterComponent.extend({ export default SelectKitFilterComponent.extend({
layout, layout,
@ -16,24 +17,23 @@ export default SelectKitFilterComponent.extend({
return isEmpty(placeholder) ? "" : I18n.t(placeholder); return isEmpty(placeholder) ? "" : I18n.t(placeholder);
}, },
actions: { @action
onPaste(event) { onPaste(event) {
const data = event.originalEvent.clipboardData; const data = event?.clipboardData;
if (!data) { if (!data) {
return; return;
} }
const parts = data.getData("text").split("|").filter(Boolean); const parts = data.getData("text").split("|").filter(Boolean);
if (parts.length > 1) { if (parts.length > 1) {
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
this.selectKit.append(parts); this.selectKit.append(parts);
return false; return false;
} }
},
}, },
}); });

View File

@ -22,7 +22,7 @@ export const ERRORS_COLLECTION = "ERRORS_COLLECTION";
const EMPTY_OBJECT = Object.freeze({}); const EMPTY_OBJECT = Object.freeze({});
const SELECT_KIT_OPTIONS = Mixin.create({ const SELECT_KIT_OPTIONS = Mixin.create({
mergedProperties: ["selectKitOptions"], concatenatedProperties: ["selectKitOptions"],
selectKitOptions: EMPTY_OBJECT, selectKitOptions: EMPTY_OBJECT,
}); });
@ -207,13 +207,14 @@ export default Component.extend(
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); this._super(...arguments);
Object.keys(this.selectKitOptions).forEach((key) => { const mergedOptions = Object.assign({}, ...this.selectKitOptions);
Object.keys(mergedOptions).forEach((key) => {
if (isPresent(this.options[key])) { if (isPresent(this.options[key])) {
this.selectKit.options.set(key, this.options[key]); this.selectKit.options.set(key, this.options[key]);
return; return;
} }
const value = this.selectKitOptions[key]; const value = mergedOptions[key];
if ( if (
key === "componentForRow" || key === "componentForRow" ||

View File

@ -1,7 +1,23 @@
{{#unless this.isHidden}} {{#unless this.isHidden}}
{{!-- filter-input-search prevents 1password from attempting autocomplete --}} {{!-- filter-input-search prevents 1password from attempting autocomplete --}}
{{!-- template-lint-disable no-down-event-binding --}} {{!-- template-lint-disable no-down-event-binding --}}
<Input tabindex={{0}} class="filter-input" placeholder={{this.placeholder}} autocomplete="off" autocorrect="off" autocapitalize="off" name="filter-input-search" spellcheck={{false}} @value={{readonly this.selectKit.filter}} {{on "pase" (action "onPaste")}} {{on "keydown" (action "onKeydown")}} {{on "keyup" (action "onKeyup")}} @type="search" {{on "input" (action "onInput")}} />
<Input
tabindex={{0}}
class="filter-input"
placeholder={{this.placeholder}}
autocomplete="off"
autocorrect="off"
autocapitalize="off"
name="filter-input-search"
spellcheck={{false}}
@value={{readonly this.selectKit.filter}}
@type="search"
{{on "paste" (action "onPaste")}}
{{on "keydown" (action "onKeydown")}}
{{on "keyup" (action "onKeyup")}}
{{on "input" (action "onInput")}}
/>
{{#if this.selectKit.options.filterIcon}} {{#if this.selectKit.options.filterIcon}}
{{d-icon this.selectKit.options.filterIcon class="filter-icon"}} {{d-icon this.selectKit.options.filterIcon class="filter-icon"}}