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:
Osama Sayegh 2023-03-29 11:49:47 +03:00 committed by GitHub
parent 69de5b161f
commit 78befbc53e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 263 deletions

View File

@ -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();
}
},
});

View File

@ -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) {

View File

@ -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");
});
});

View File

@ -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 () {