DEV: Remove `{{user-selector}}` (#17753)
`{{user-selector}}` was deprecated in 293fd1f743
more than 2 years ago and it's time we deleted it.
This commit is contained in:
parent
69de5b161f
commit
78befbc53e
|
@ -1,195 +0,0 @@
|
||||||
import { bind, observes, on } from "discourse-common/utils/decorators";
|
|
||||||
import TextField from "discourse/components/text-field";
|
|
||||||
import { findRawTemplate } from "discourse-common/lib/raw-templates";
|
|
||||||
import { isEmpty } from "@ember/utils";
|
|
||||||
import userSearch from "discourse/lib/user-search";
|
|
||||||
import deprecated from "discourse-common/lib/deprecated";
|
|
||||||
|
|
||||||
export default TextField.extend({
|
|
||||||
autocorrect: false,
|
|
||||||
autocapitalize: false,
|
|
||||||
name: "user-selector",
|
|
||||||
canReceiveUpdates: false,
|
|
||||||
single: false,
|
|
||||||
fullWidthWrap: false,
|
|
||||||
|
|
||||||
@on("init")
|
|
||||||
deprecateComponent() {
|
|
||||||
deprecated(
|
|
||||||
"The `<UserSelector>` component is deprecated. Please use `<EmailGroupUserChooser>` instead.",
|
|
||||||
{ since: "2.7", dropFrom: "2.8", id: "discourse.user-selector-component" }
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
@bind
|
|
||||||
_paste(event) {
|
|
||||||
let pastedText = "";
|
|
||||||
|
|
||||||
if (window.clipboardData && window.clipboardData.getData) {
|
|
||||||
// IE
|
|
||||||
pastedText = window.clipboardData.getData("Text");
|
|
||||||
} else if (event.clipboardData && event.clipboardData.getData) {
|
|
||||||
pastedText = event.clipboardData.getData("text/plain");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pastedText.length > 0) {
|
|
||||||
this.importText(pastedText);
|
|
||||||
event.preventDefault();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
didUpdateAttrs() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
if (this.canReceiveUpdates) {
|
|
||||||
this._createAutocompleteInstance({ updateData: true });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
@on("willDestroyElement")
|
|
||||||
_destroyAutocompleteInstance() {
|
|
||||||
$(this.element).autocomplete("destroy");
|
|
||||||
this.element.removeEventListener("paste", this._paste);
|
|
||||||
},
|
|
||||||
|
|
||||||
@on("didInsertElement")
|
|
||||||
_createAutocompleteInstance(opts) {
|
|
||||||
const bool = (n) => {
|
|
||||||
const val = this[n];
|
|
||||||
return val === true || val === "true";
|
|
||||||
};
|
|
||||||
|
|
||||||
let selected = [],
|
|
||||||
groups = [],
|
|
||||||
currentUser = this.currentUser,
|
|
||||||
includeMentionableGroups = bool("includeMentionableGroups"),
|
|
||||||
includeMessageableGroups = bool("includeMessageableGroups"),
|
|
||||||
includeGroups = bool("includeGroups"),
|
|
||||||
allowedUsers = bool("allowedUsers"),
|
|
||||||
excludeCurrentUser = bool("excludeCurrentUser"),
|
|
||||||
single = bool("single"),
|
|
||||||
allowAny = bool("allowAny"),
|
|
||||||
disabled = bool("disabled"),
|
|
||||||
allowEmails = bool("allowEmails"),
|
|
||||||
fullWidthWrap = bool("fullWidthWrap");
|
|
||||||
|
|
||||||
const allExcludedUsernames = () => {
|
|
||||||
// hack works around some issues with allowAny eventing
|
|
||||||
let usernames = single ? [] : selected;
|
|
||||||
|
|
||||||
if (currentUser && excludeCurrentUser) {
|
|
||||||
usernames = usernames.concat([currentUser.username]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return usernames.concat(this.excludedUsernames || []);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.element.addEventListener("paste", this._paste);
|
|
||||||
|
|
||||||
const userSelectorComponent = this;
|
|
||||||
|
|
||||||
$(this.element)
|
|
||||||
.val(this.usernames)
|
|
||||||
.autocomplete({
|
|
||||||
template: findRawTemplate("user-selector-autocomplete"),
|
|
||||||
disabled,
|
|
||||||
single,
|
|
||||||
allowAny,
|
|
||||||
updateData: opts && opts.updateData ? opts.updateData : false,
|
|
||||||
fullWidthWrap,
|
|
||||||
|
|
||||||
dataSource(term) {
|
|
||||||
return userSearch({
|
|
||||||
term,
|
|
||||||
topicId: userSelectorComponent.topicId,
|
|
||||||
exclude: allExcludedUsernames(),
|
|
||||||
includeGroups,
|
|
||||||
allowedUsers,
|
|
||||||
includeMentionableGroups,
|
|
||||||
includeMessageableGroups,
|
|
||||||
groupMembersOf: userSelectorComponent.groupMembersOf,
|
|
||||||
allowEmails,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
transformComplete(v) {
|
|
||||||
if (v.username || v.name) {
|
|
||||||
if (!v.username) {
|
|
||||||
groups.push(v.name);
|
|
||||||
}
|
|
||||||
return v.username || v.name;
|
|
||||||
} else {
|
|
||||||
const excludes = allExcludedUsernames();
|
|
||||||
return v.usernames.filter((item) => !excludes.includes(item));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onChangeItems(items) {
|
|
||||||
let hasGroups = false;
|
|
||||||
items = items.map((i) => {
|
|
||||||
if (groups.includes(i)) {
|
|
||||||
hasGroups = true;
|
|
||||||
}
|
|
||||||
return i.username ? i.username : i;
|
|
||||||
});
|
|
||||||
|
|
||||||
let previouslySelected = [];
|
|
||||||
if (Array.isArray(userSelectorComponent.usernames)) {
|
|
||||||
previouslySelected = userSelectorComponent.usernames;
|
|
||||||
} else {
|
|
||||||
if (userSelectorComponent.usernames) {
|
|
||||||
previouslySelected = userSelectorComponent.usernames.split(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
userSelectorComponent.setProperties({
|
|
||||||
usernames: items.join(","),
|
|
||||||
hasGroups,
|
|
||||||
});
|
|
||||||
selected = items;
|
|
||||||
|
|
||||||
if (userSelectorComponent.onChangeCallback) {
|
|
||||||
userSelectorComponent.onChangeCallback(
|
|
||||||
previouslySelected,
|
|
||||||
selected
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reverseTransform(i) {
|
|
||||||
return { username: i };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
importText(text) {
|
|
||||||
let usernames = [];
|
|
||||||
if ((this.usernames || "").length > 0) {
|
|
||||||
usernames = this.usernames.split(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
(text || "").split(/[, \n]+/).forEach((val) => {
|
|
||||||
val = val.replace(/^@+/, "").trim();
|
|
||||||
if (
|
|
||||||
val.length > 0 &&
|
|
||||||
(!this.excludedUsernames || !this.excludedUsernames.includes(val))
|
|
||||||
) {
|
|
||||||
usernames.push(val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.set("usernames", usernames.uniq().join(","));
|
|
||||||
|
|
||||||
if (!this.canReceiveUpdates) {
|
|
||||||
this._createAutocompleteInstance({ updateData: true });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// THIS IS A HUGE HACK TO SUPPORT CLEARING THE INPUT
|
|
||||||
@observes("usernames")
|
|
||||||
_clearInput() {
|
|
||||||
if (arguments.length > 1 && isEmpty(this.usernames)) {
|
|
||||||
$(this.element).parent().find("a").click();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -21,7 +21,73 @@ module(
|
||||||
await this.subject.expand();
|
await this.subject.expand();
|
||||||
await paste(query(".filter-input"), "foo,bar");
|
await paste(query(".filter-input"), "foo,bar");
|
||||||
|
|
||||||
assert.equal(this.subject.header().value(), "foo,bar");
|
assert.strictEqual(this.subject.header().value(), "foo,bar");
|
||||||
|
|
||||||
|
await paste(query(".filter-input"), "evil,trout");
|
||||||
|
assert.strictEqual(this.subject.header().value(), "foo,bar,evil,trout");
|
||||||
|
|
||||||
|
await paste(query(".filter-input"), "names with spaces");
|
||||||
|
assert.strictEqual(
|
||||||
|
this.subject.header().value(),
|
||||||
|
"foo,bar,evil,trout,names,with,spaces"
|
||||||
|
);
|
||||||
|
|
||||||
|
await paste(query(".filter-input"), "@osama,@sam");
|
||||||
|
assert.strictEqual(
|
||||||
|
this.subject.header().value(),
|
||||||
|
"foo,bar,evil,trout,names,with,spaces,osama,sam"
|
||||||
|
);
|
||||||
|
|
||||||
|
await paste(query(".filter-input"), "new\nlines");
|
||||||
|
assert.strictEqual(
|
||||||
|
this.subject.header().value(),
|
||||||
|
"foo,bar,evil,trout,names,with,spaces,osama,sam,new,lines"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("excluding usernames", async function (assert) {
|
||||||
|
pretender.get("/u/search/users", () => {
|
||||||
|
const users = [
|
||||||
|
{
|
||||||
|
username: "osama",
|
||||||
|
avatar_template:
|
||||||
|
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: "joshua",
|
||||||
|
avatar_template:
|
||||||
|
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: "sam",
|
||||||
|
avatar_template:
|
||||||
|
"https://avatars.discourse.org/v3/letter/t/41988e/{size}.png",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return response({ users });
|
||||||
|
});
|
||||||
|
|
||||||
|
this.set("excludedUsernames", ["osama", "joshua"]);
|
||||||
|
await render(
|
||||||
|
hbs`<EmailGroupUserChooser @options={{hash excludedUsernames=this.excludedUsernames}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.subject.expand();
|
||||||
|
await this.subject.fillInFilter("a");
|
||||||
|
|
||||||
|
let suggestions = this.subject.displayedContent().mapBy("id");
|
||||||
|
assert.deepEqual(suggestions, ["sam"]);
|
||||||
|
|
||||||
|
this.set("excludedUsernames", ["osama"]);
|
||||||
|
await render(
|
||||||
|
hbs`<EmailGroupUserChooser @options={{hash excludedUsernames=this.excludedUsernames}} />`
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.subject.expand();
|
||||||
|
await this.subject.fillInFilter("a");
|
||||||
|
|
||||||
|
suggestions = this.subject.displayedContent().mapBy("id").sort();
|
||||||
|
assert.deepEqual(suggestions, ["joshua", "sam"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("doesn't show user status by default", async function (assert) {
|
test("doesn't show user status by default", async function (assert) {
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
import { module, test } from "qunit";
|
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
|
||||||
import { render } from "@ember/test-helpers";
|
|
||||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
|
||||||
import { withSilencedDeprecationsAsync } from "discourse-common/lib/deprecated";
|
|
||||||
|
|
||||||
function paste(element, text) {
|
|
||||||
let e = new Event("paste");
|
|
||||||
e.clipboardData = { getData: () => text };
|
|
||||||
element.dispatchEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
module("Integration | Component | user-selector", function (hooks) {
|
|
||||||
setupRenderingTest(hooks);
|
|
||||||
|
|
||||||
test("pasting a list of usernames", async function (assert) {
|
|
||||||
this.set("usernames", "evil,trout");
|
|
||||||
|
|
||||||
await withSilencedDeprecationsAsync(
|
|
||||||
"discourse.user-selector-component",
|
|
||||||
async () => {
|
|
||||||
await render(
|
|
||||||
hbs`<UserSelector @usernames={{this.usernames}} class="test-selector" />`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let element = query(".test-selector");
|
|
||||||
|
|
||||||
assert.strictEqual(this.get("usernames"), "evil,trout");
|
|
||||||
paste(element, "zip,zap,zoom");
|
|
||||||
assert.strictEqual(this.get("usernames"), "evil,trout,zip,zap,zoom");
|
|
||||||
paste(element, "evil,abc,abc,abc");
|
|
||||||
assert.strictEqual(this.get("usernames"), "evil,trout,zip,zap,zoom,abc");
|
|
||||||
|
|
||||||
this.set("usernames", "");
|
|
||||||
paste(element, "names with spaces");
|
|
||||||
assert.strictEqual(this.get("usernames"), "names,with,spaces");
|
|
||||||
|
|
||||||
this.set("usernames", null);
|
|
||||||
paste(element, "@eviltrout,@codinghorror sam");
|
|
||||||
assert.strictEqual(this.get("usernames"), "eviltrout,codinghorror,sam");
|
|
||||||
|
|
||||||
this.set("usernames", null);
|
|
||||||
paste(element, "eviltrout\nsam\ncodinghorror");
|
|
||||||
assert.strictEqual(this.get("usernames"), "eviltrout,sam,codinghorror");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("excluding usernames", async function (assert) {
|
|
||||||
this.set("usernames", "mark");
|
|
||||||
this.set("excludedUsernames", ["jeff", "sam", "robin"]);
|
|
||||||
|
|
||||||
await withSilencedDeprecationsAsync(
|
|
||||||
"discourse.user-selector-component",
|
|
||||||
async () => {
|
|
||||||
await render(
|
|
||||||
hbs`<UserSelector @usernames={{this.usernames}} @excludedUsernames={{this.excludedUsernames}} class="test-selector" />`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let element = query(".test-selector");
|
|
||||||
paste(element, "roman,penar,jeff,robin");
|
|
||||||
assert.strictEqual(this.get("usernames"), "mark,roman,penar");
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -29,6 +29,7 @@ export default MultiSelectComponent.extend({
|
||||||
groupMembersOf: undefined,
|
groupMembersOf: undefined,
|
||||||
excludeCurrentUser: false,
|
excludeCurrentUser: false,
|
||||||
customSearchOptions: undefined,
|
customSearchOptions: undefined,
|
||||||
|
excludedUsernames: undefined,
|
||||||
},
|
},
|
||||||
|
|
||||||
content: computed("value.[]", function () {
|
content: computed("value.[]", function () {
|
||||||
|
|
Loading…
Reference in New Issue