This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/components/user-selector.js
2020-03-12 13:29:55 -04:00

192 lines
5.2 KiB
JavaScript

import { isEmpty } from "@ember/utils";
import { on, observes } from "discourse-common/utils/decorators";
import TextField from "discourse/components/text-field";
import userSearch from "discourse/lib/user-search";
import { findRawTemplate } from "discourse/lib/raw-templates";
export default TextField.extend({
autocorrect: false,
autocapitalize: false,
name: "user-selector",
canReceiveUpdates: false,
single: false,
fullWidthWrap: false,
init() {
this._super(...arguments);
this._paste = e => {
let pastedText = "";
if (window.clipboardData && window.clipboardData.getData) {
// IE
pastedText = window.clipboardData.getData("Text");
} else if (e.clipboardData && e.clipboardData.getData) {
pastedText = e.clipboardData.getData("text/plain");
}
if (pastedText.length > 0) {
this.importText(pastedText);
e.preventDefault();
return false;
}
};
},
didUpdateAttrs() {
this._super(...arguments);
if (this.canReceiveUpdates) {
this._createAutocompleteInstance({ updateData: true });
}
},
@on("willDestroyElement")
_destroyAutocompleteInstance() {
$(this.element).autocomplete("destroy");
this.element.addEventListener("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.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.indexOf(item) === -1);
}
},
onChangeItems(items) {
let hasGroups = false;
items = items.map(i => {
if (groups.indexOf(i) > -1) {
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();
}
}
});