debian-mirror-gitlab/app/assets/javascripts/vue_shared/components/gl_mentions.vue
2020-08-09 17:41:57 +05:30

117 lines
3.4 KiB
Vue

<script>
import { escape } from 'lodash';
import Tribute from 'tributejs';
import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from '~/lib/utils/common_utils';
import SidebarMediator from '~/sidebar/sidebar_mediator';
/**
* 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 menuItemTemplate({ original }) {
const rectAvatarClass = original.type === 'Group' ? 'rect-avatar' : '';
const avatarClasses = `avatar avatar-inline center s26 ${rectAvatarClass}
gl-display-inline-flex! gl-align-items-center gl-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(original.name);
const count = original.count && !original.mentionsDisabled ? ` (${original.count})` : '';
const icon = original.mentionsDisabled
? spriteIcon('notifications-off', 's16 gl-vertical-align-middle gl-ml-3')
: '';
return `${avatarTag}
${original.username}
<small class="gl-text-small gl-font-weight-normal gl-reset-color">${name}${count}</small>
${icon}`;
}
export default {
name: 'GlMentions',
props: {
dataSources: {
type: Object,
required: false,
default: () => gl.GfmAutoComplete?.dataSources || {},
},
},
data() {
return {
assignees: undefined,
members: undefined,
};
},
mounted() {
this.tribute = new Tribute({
trigger: '@',
fillAttr: 'username',
lookup: value => value.name + value.username,
menuItemTemplate,
values: this.getMembers,
});
const input = this.$slots.default[0].elm;
this.tribute.attach(input);
},
beforeDestroy() {
const input = this.$slots.default[0].elm;
this.tribute.detach(input);
},
methods: {
/**
* 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
*/
getMembers(inputText, processValues) {
if (this.members) {
processValues(this.getFilteredMembers());
} else if (this.dataSources.members) {
axios
.get(this.dataSources.members)
.then(response => {
this.members = response.data;
processValues(this.getFilteredMembers());
})
.catch(() => {});
} else {
processValues([]);
}
},
getFilteredMembers() {
const fullText = this.$slots.default[0].elm.value;
if (!this.assignees) {
this.assignees =
SidebarMediator.singleton?.store?.assignees?.map(assignee => assignee.username) || [];
}
if (fullText.startsWith('/assign @')) {
return this.members.filter(member => !this.assignees.includes(member.username));
}
if (fullText.startsWith('/unassign @')) {
return this.members.filter(member => this.assignees.includes(member.username));
}
return this.members;
},
},
render(createElement) {
return createElement('div', this.$slots.default);
},
};
</script>