diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 11:27:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 11:27:35 +0300 |
commit | 7e9c479f7de77702622631cff2628a9c8dcbc627 (patch) | |
tree | c8f718a08e110ad7e1894510980d2155a6549197 /app/assets/javascripts/gfm_auto_complete.js | |
parent | e852b0ae16db4052c1c567d9efa4facc81146e88 (diff) |
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/gfm_auto_complete.js')
-rw-r--r-- | app/assets/javascripts/gfm_auto_complete.js | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index 62948f74aaa..202f04f98f6 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -1,9 +1,12 @@ import $ from 'jquery'; import '~/lib/utils/jquery_at_who'; import { escape, template } from 'lodash'; +import { s__ } from '~/locale'; import SidebarMediator from '~/sidebar/sidebar_mediator'; +import { isUserBusy } from '~/set_status_modal/utils'; import glRegexp from './lib/utils/regexp'; import AjaxCache from './lib/utils/ajax_cache'; +import axios from '~/lib/utils/axios_utils'; import { spriteIcon } from './lib/utils/common_utils'; import * as Emoji from '~/emoji'; @@ -39,6 +42,7 @@ export function membersBeforeSave(members) { title: sanitize(title), search: sanitize(`${member.username} ${member.name}`), icon: avatarIcon, + availability: member.availability, }; }); } @@ -52,6 +56,7 @@ export const defaultAutocompleteConfig = { milestones: true, labels: true, snippets: true, + vulnerabilities: true, }; class GfmAutoComplete { @@ -59,6 +64,7 @@ class GfmAutoComplete { this.dataSources = dataSources; this.cachedData = {}; this.isLoadingData = {}; + this.previousQuery = ''; } setup(input, enableMap = defaultAutocompleteConfig) { @@ -253,13 +259,17 @@ class GfmAutoComplete { alias: 'users', displayTpl(value) { let tmpl = GfmAutoComplete.Loading.template; - const { avatarTag, username, title, icon } = value; + const { avatarTag, username, title, icon, availability } = value; if (username != null) { tmpl = GfmAutoComplete.Members.templateFunction({ avatarTag, username, title, icon, + availabilityStatus: + availability && isUserBusy(availability) + ? `<span class="gl-text-gray-500"> ${s__('UserAvailability|(Busy)')}</span>` + : '', }); } return tmpl; @@ -554,7 +564,7 @@ class GfmAutoComplete { } getDefaultCallbacks() { - const fetchData = this.fetchData.bind(this); + const self = this; return { sorter(query, items, searchKey) { @@ -567,7 +577,14 @@ class GfmAutoComplete { }, filter(query, data, searchKey) { if (GfmAutoComplete.isLoading(data)) { - fetchData(this.$inputor, this.at); + self.fetchData(this.$inputor, this.at); + return data; + } else if ( + GfmAutoComplete.isTypeWithBackendFiltering(this.at) && + self.previousQuery !== query + ) { + self.fetchData(this.$inputor, this.at, query); + self.previousQuery = query; return data; } return $.fn.atwho.default.callbacks.filter(query, data, searchKey); @@ -615,13 +632,22 @@ class GfmAutoComplete { }; } - fetchData($input, at) { + fetchData($input, at, search) { if (this.isLoadingData[at]) return; this.isLoadingData[at] = true; const dataSource = this.dataSources[GfmAutoComplete.atTypeMap[at]]; - if (this.cachedData[at]) { + if (GfmAutoComplete.isTypeWithBackendFiltering(at)) { + axios + .get(dataSource, { params: { search } }) + .then(({ data }) => { + this.loadData($input, at, data); + }) + .catch(() => { + this.isLoadingData[at] = false; + }); + } else if (this.cachedData[at]) { this.loadData($input, at, this.cachedData[at]); } else if (GfmAutoComplete.atTypeMap[at] === 'emojis') { this.loadEmojiData($input, at).catch(() => {}); @@ -707,7 +733,9 @@ class GfmAutoComplete { // https://github.com/ichord/At.js const atSymbolsWithBar = Object.keys(controllers) .join('|') - .replace(/[$]/, '\\$&'); + .replace(/[$]/, '\\$&') + .replace(/([[\]:])/g, '\\$1'); + const atSymbolsWithoutBar = Object.keys(controllers).join(''); const targetSubtext = subtext.split(GfmAutoComplete.regexSubtext).pop(); const resultantFlag = flag.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); @@ -738,9 +766,14 @@ GfmAutoComplete.atTypeMap = { '~': 'labels', '%': 'milestones', '/': 'commands', + '[vulnerability:': 'vulnerabilities', $: 'snippets', }; +GfmAutoComplete.typesWithBackendFiltering = ['vulnerabilities']; +GfmAutoComplete.isTypeWithBackendFiltering = type => + GfmAutoComplete.typesWithBackendFiltering.includes(GfmAutoComplete.atTypeMap[type]); + function findEmoji(name) { return Emoji.searchEmoji(name, { match: 'contains', raw: true }).sort((a, b) => { if (a.index !== b.index) { @@ -775,8 +808,10 @@ GfmAutoComplete.Emoji = { }; // Team Members GfmAutoComplete.Members = { - templateFunction({ avatarTag, username, title, icon }) { - return `<li>${avatarTag} ${username} <small>${escape(title)}</small> ${icon}</li>`; + templateFunction({ avatarTag, username, title, icon, availabilityStatus }) { + return `<li>${avatarTag} ${username} <small>${escape( + title, + )}${availabilityStatus}</small> ${icon}</li>`; }, }; GfmAutoComplete.Labels = { |