summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js')
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js69
1 files changed, 61 insertions, 8 deletions
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
index 2581888b504..809932b0f29 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
@@ -1,16 +1,24 @@
import { escape, last } from 'lodash';
+import * as Emoji from '~/emoji';
import { spriteIcon } from '~/lib/utils/common_utils';
const groupType = 'Group'; // eslint-disable-line @gitlab/require-i18n-strings
+// Number of users to show in the autocomplete menu to avoid doing a mass fetch of 100+ avatars
+const memberLimit = 10;
+
const nonWordOrInteger = /\W|^\d+$/;
+export const menuItemLimit = 100;
+
export const GfmAutocompleteType = {
+ Emojis: 'emojis',
Issues: 'issues',
Labels: 'labels',
Members: 'members',
MergeRequests: 'mergeRequests',
Milestones: 'milestones',
+ QuickActions: 'commands',
Snippets: 'snippets',
};
@@ -21,10 +29,21 @@ function doesCurrentLineStartWith(searchString, fullText, selectionStart) {
}
export const tributeConfig = {
+ [GfmAutocompleteType.Emojis]: {
+ config: {
+ trigger: ':',
+ lookup: (value) => value,
+ menuItemLimit,
+ menuItemTemplate: ({ original }) => `${original} ${Emoji.glEmojiTag(original)}`,
+ selectTemplate: ({ original }) => `:${original}:`,
+ },
+ },
+
[GfmAutocompleteType.Issues]: {
config: {
trigger: '#',
- lookup: value => `${value.iid}${value.title}`,
+ lookup: (value) => `${value.iid}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) =>
`<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `#${original.iid}`,
@@ -35,6 +54,7 @@ export const tributeConfig = {
config: {
trigger: '~',
lookup: 'title',
+ menuItemLimit,
menuItemTemplate: ({ original }) => `
<span class="dropdown-label-box" style="background: ${escape(original.color)};"></span>
${escape(original.title)}`,
@@ -45,11 +65,11 @@ export const tributeConfig = {
},
filterValues({ collection, fullText, selectionStart }) {
if (doesCurrentLineStartWith('/label', fullText, selectionStart)) {
- return collection.filter(label => !label.set);
+ return collection.filter((label) => !label.set);
}
if (doesCurrentLineStartWith('/unlabel', fullText, selectionStart)) {
- return collection.filter(label => label.set);
+ return collection.filter((label) => label.set);
}
return collection;
@@ -60,8 +80,9 @@ export const tributeConfig = {
config: {
trigger: '@',
fillAttr: 'username',
- lookup: value =>
+ lookup: (value) =>
value.type === groupType ? last(value.name.split(' / ')) : `${value.name}${value.username}`,
+ menuItemLimit: memberLimit,
menuItemTemplate: ({ original }) => {
const commonClasses = 'gl-avatar gl-avatar-s24 gl-flex-shrink-0';
const noAvatarClasses = `${commonClasses} gl-rounded-small
@@ -101,11 +122,11 @@ export const tributeConfig = {
},
filterValues({ assignees, collection, fullText, selectionStart }) {
if (doesCurrentLineStartWith('/assign', fullText, selectionStart)) {
- return collection.filter(member => !assignees.includes(member.username));
+ return collection.filter((member) => !assignees.includes(member.username));
}
if (doesCurrentLineStartWith('/unassign', fullText, selectionStart)) {
- return collection.filter(member => assignees.includes(member.username));
+ return collection.filter((member) => assignees.includes(member.username));
}
return collection;
@@ -115,7 +136,8 @@ export const tributeConfig = {
[GfmAutocompleteType.MergeRequests]: {
config: {
trigger: '!',
- lookup: value => `${value.iid}${value.title}`,
+ lookup: (value) => `${value.iid}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) =>
`<small>${original.reference || original.iid}</small> ${escape(original.title)}`,
selectTemplate: ({ original }) => original.reference || `!${original.iid}`,
@@ -126,16 +148,47 @@ export const tributeConfig = {
config: {
trigger: '%',
lookup: 'title',
+ menuItemLimit,
menuItemTemplate: ({ original }) => escape(original.title),
selectTemplate: ({ original }) => `%"${escape(original.title)}"`,
},
},
+ [GfmAutocompleteType.QuickActions]: {
+ config: {
+ trigger: '/',
+ fillAttr: 'name',
+ lookup: (value) => `${value.name}${value.aliases.join()}`,
+ menuItemLimit,
+ menuItemTemplate: ({ original }) => {
+ const aliases = original.aliases.length
+ ? `<small>(or /${original.aliases.join(', /')})</small>`
+ : '';
+
+ const params = original.params.length ? `<small>${original.params.join(' ')}</small>` : '';
+
+ let description = '';
+
+ if (original.warning) {
+ const confidentialIcon =
+ original.icon === 'confidential' ? spriteIcon('eye-slash', 's16 gl-mr-2') : '';
+ description = `<small>${confidentialIcon}<em>${original.warning}</em></small>`;
+ } else if (original.description) {
+ description = `<small><em>${original.description}</em></small>`;
+ }
+
+ return `<div>/${original.name} ${aliases} ${params}</div>
+ <div>${description}</div>`;
+ },
+ },
+ },
+
[GfmAutocompleteType.Snippets]: {
config: {
trigger: '$',
fillAttr: 'id',
- lookup: value => `${value.id}${value.title}`,
+ lookup: (value) => `${value.id}${value.title}`,
+ menuItemLimit,
menuItemTemplate: ({ original }) => `<small>${original.id}</small> ${escape(original.title)}`,
},
},