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 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) {
|
||||
|
|
|
@ -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,
|
||||
excludeCurrentUser: false,
|
||||
customSearchOptions: undefined,
|
||||
excludedUsernames: undefined,
|
||||
},
|
||||
|
||||
content: computed("value.[]", function () {
|
||||
|
|
Loading…
Reference in New Issue