debian-mirror-gitlab/app/assets/javascripts/vue_shared/components/gl_mentions.vue

118 lines
3.4 KiB
Vue
Raw Normal View History

2020-04-08 14:13:33 +05:30
<script>
2020-06-23 00:09:42 +05:30
import { escape } from 'lodash';
2020-04-08 14:13:33 +05:30
import Tribute from 'tributejs';
import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from '~/lib/utils/common_utils';
2020-07-28 23:09:34 +05:30
import SidebarMediator from '~/sidebar/sidebar_mediator';
2020-04-08 14:13:33 +05:30
/**
* Creates the HTML template for each row of the mentions dropdown.
*
2020-07-28 23:09:34 +05:30
* @param original - An object from the array returned from the `autocomplete_sources/members` API
* @returns {string} - An HTML template
2020-04-08 14:13:33 +05:30
*/
2020-06-23 00:09:42 +05:30
function menuItemTemplate({ original }) {
2020-04-08 14:13:33 +05:30
const rectAvatarClass = original.type === 'Group' ? 'rect-avatar' : '';
const avatarClasses = `avatar avatar-inline center s26 ${rectAvatarClass}
2020-07-28 23:09:34 +05:30
gl-display-inline-flex! gl-align-items-center gl-justify-content-center`;
2020-04-08 14:13:33 +05:30
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>`;
2020-06-23 00:09:42 +05:30
const name = escape(original.name);
2020-04-08 14:13:33 +05:30
const count = original.count && !original.mentionsDisabled ? ` (${original.count})` : '';
const icon = original.mentionsDisabled
2020-06-23 00:09:42 +05:30
? spriteIcon('notifications-off', 's16 gl-vertical-align-middle gl-ml-3')
2020-04-08 14:13:33 +05:30
: '';
return `${avatarTag}
${original.username}
2020-06-23 00:09:42 +05:30
<small class="gl-text-small gl-font-weight-normal gl-reset-color">${name}${count}</small>
2020-04-08 14:13:33 +05:30
${icon}`;
}
export default {
name: 'GlMentions',
props: {
dataSources: {
type: Object,
required: false,
default: () => gl.GfmAutoComplete?.dataSources || {},
},
},
data() {
return {
2020-07-28 23:09:34 +05:30
assignees: undefined,
2020-04-08 14:13:33 +05:30
members: undefined,
};
},
mounted() {
2020-06-23 00:09:42 +05:30
this.tribute = new Tribute({
trigger: '@',
fillAttr: 'username',
lookup: value => value.name + value.username,
menuItemTemplate,
values: this.getMembers,
});
2020-04-08 14:13:33 +05:30
const input = this.$slots.default[0].elm;
this.tribute.attach(input);
},
beforeDestroy() {
const input = this.$slots.default[0].elm;
2020-06-23 00:09:42 +05:30
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) {
2020-07-28 23:09:34 +05:30
processValues(this.getFilteredMembers());
2020-06-23 00:09:42 +05:30
} else if (this.dataSources.members) {
axios
.get(this.dataSources.members)
.then(response => {
this.members = response.data;
2020-07-28 23:09:34 +05:30
processValues(this.getFilteredMembers());
2020-06-23 00:09:42 +05:30
})
.catch(() => {});
} else {
processValues([]);
}
},
2020-07-28 23:09:34 +05:30
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;
},
2020-04-08 14:13:33 +05:30
},
2020-06-23 00:09:42 +05:30
render(createElement) {
return createElement('div', this.$slots.default);
2020-04-08 14:13:33 +05:30
},
};
</script>