diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/gl_mentions.vue | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/gl_mentions.vue b/app/assets/javascripts/vue_shared/components/gl_mentions.vue new file mode 100644 index 00000000000..bbf293664a6 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/gl_mentions.vue @@ -0,0 +1,101 @@ +<script> +import escape from 'lodash/escape'; +import sanitize from 'sanitize-html'; +import Tribute from 'tributejs'; +import axios from '~/lib/utils/axios_utils'; +import { spriteIcon } from '~/lib/utils/common_utils'; + +/** + * Creates the HTML template for each row of the mentions dropdown. + * + * @param original An object from the array returned from the `autocomplete_sources/members` API + * @returns {string} An HTML template + */ +function createMenuItemTemplate({ original }) { + const rectAvatarClass = original.type === 'Group' ? 'rect-avatar' : ''; + + const avatarClasses = `avatar avatar-inline center s26 ${rectAvatarClass} + align-items-center d-inline-flex justify-content-center`; + + const avatarTag = original.avatar_url + ? `<img + src="${original.avatar_url}" + alt="${original.username}'s avatar" + class="${avatarClasses}"/>` + : `<div class="${avatarClasses}">${original.username.charAt(0).toUpperCase()}</div>`; + + const name = escape(sanitize(original.name)); + + const count = original.count && !original.mentionsDisabled ? ` (${original.count})` : ''; + + const icon = original.mentionsDisabled + ? spriteIcon('notifications-off', 's16 vertical-align-middle prepend-left-5') + : ''; + + return `${avatarTag} + ${original.username} + <small class="small font-weight-normal gl-color-inherit">${name}${count}</small> + ${icon}`; +} + +/** + * Creates the list of users to show in the mentions dropdown. + * + * @param inputText The text entered by the user in the mentions input field + * @param processValues Callback function to set the list of users to show in the mentions dropdown + */ +function getMembers(inputText, processValues) { + if (this.members) { + processValues(this.members); + } else if (this.dataSources.members) { + axios + .get(this.dataSources.members) + .then(response => { + this.members = response.data; + processValues(response.data); + }) + .catch(() => {}); + } else { + processValues([]); + } +} + +export default { + name: 'GlMentions', + props: { + dataSources: { + type: Object, + required: false, + default: () => gl.GfmAutoComplete?.dataSources || {}, + }, + }, + data() { + return { + members: undefined, + options: { + trigger: '@', + fillAttr: 'username', + lookup(value) { + return value.name + value.username; + }, + menuItemTemplate: createMenuItemTemplate.bind(this), + values: getMembers.bind(this), + }, + }; + }, + mounted() { + const input = this.$slots.default[0].elm; + this.tribute = new Tribute(this.options); + this.tribute.attach(input); + }, + beforeDestroy() { + const input = this.$slots.default[0].elm; + if (this.tribute) { + this.tribute.detach(input); + } + }, + render(h) { + return h('div', this.$slots.default); + }, +}; +</script> |