Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Zallmann <tzallmann@gitlab.com>2017-12-07 01:09:33 +0300
committerTim Zallmann <tzallmann@gitlab.com>2017-12-07 01:09:33 +0300
commit7619bdd6594e12a51594fa2f3fd47291579db5da (patch)
treec7361a1410c1760958755fd185ff0f45892b12d9 /app/assets/javascripts
parent743451b231445bfc2ee295d8097bdcdeb1ff47ad (diff)
parent68f0092c8f3f6f29d1cbdd4511aef84875519fbe (diff)
Merge branch '22680-unlabel-slash-command-limit-autocomplete-to-applied-labels' into 'master'
Resolve "/unlabel quick action - limit autocomplete to applied labels" Closes #22680 and #27319 See merge request gitlab-org/gitlab-ce!11110
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js75
1 files changed, 61 insertions, 14 deletions
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index a642464c920..d918d80df8d 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -287,6 +287,10 @@ class GfmAutoComplete {
}
setupLabels($input) {
+ const fetchData = this.fetchData.bind(this);
+ const LABEL_COMMAND = { LABEL: '/label', UNLABEL: '/unlabel', RELABEL: '/relabel' };
+ let command = '';
+
$input.atwho({
at: '~',
alias: 'labels',
@@ -309,8 +313,45 @@ class GfmAutoComplete {
title: sanitize(m.title),
color: m.color,
search: m.title,
+ set: m.set,
}));
},
+ matcher(flag, subtext) {
+ const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers);
+ const subtextNodes = subtext.split(/\n+/g).pop().split(GfmAutoComplete.regexSubtext);
+
+ // Check if ~ is followed by '/label', '/relabel' or '/unlabel' commands.
+ command = subtextNodes.find((node) => {
+ if (node === LABEL_COMMAND.LABEL ||
+ node === LABEL_COMMAND.RELABEL ||
+ node === LABEL_COMMAND.UNLABEL) { return node; }
+ return null;
+ });
+
+ return match && match.length ? match[1] : null;
+ },
+ filter(query, data, searchKey) {
+ if (GfmAutoComplete.isLoading(data)) {
+ fetchData(this.$inputor, this.at);
+ return data;
+ }
+
+ if (data === GfmAutoComplete.defaultLoadingData) {
+ return $.fn.atwho.default.callbacks.filter(query, data, searchKey);
+ }
+
+ // The `LABEL_COMMAND.RELABEL` is intentionally skipped
+ // because we want to return all the labels (unfiltered) for that command.
+ if (command === LABEL_COMMAND.LABEL) {
+ // Return labels with set: undefined.
+ return data.filter(label => !label.set);
+ } else if (command === LABEL_COMMAND.UNLABEL) {
+ // Return labels with set: true.
+ return data.filter(label => label.set);
+ }
+
+ return data;
+ },
},
});
}
@@ -346,20 +387,7 @@ class GfmAutoComplete {
return resultantValue;
},
matcher(flag, subtext) {
- // The below is taken from At.js source
- // Tweaked to commands to start without a space only if char before is a non-word character
- // https://github.com/ichord/At.js
- const atSymbolsWithBar = Object.keys(this.app.controllers).join('|');
- const atSymbolsWithoutBar = Object.keys(this.app.controllers).join('');
- const targetSubtext = subtext.split(/\s+/g).pop();
- const resultantFlag = flag.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
-
- const accentAChar = decodeURI('%C3%80');
- const accentYChar = decodeURI('%C3%BF');
-
- const regexp = new RegExp(`^(?:\\B|[^a-zA-Z0-9_${atSymbolsWithoutBar}]|\\s)${resultantFlag}(?!${atSymbolsWithBar})((?:[A-Za-z${accentAChar}-${accentYChar}0-9_'.+-]|[^\\x00-\\x7a])*)$`, 'gi');
-
- const match = regexp.exec(targetSubtext);
+ const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers);
if (match) {
return match[1];
@@ -420,8 +448,27 @@ class GfmAutoComplete {
return dataToInspect &&
(dataToInspect === loadingState || dataToInspect.name === loadingState);
}
+
+ static defaultMatcher(flag, subtext, controllers) {
+ // The below is taken from At.js source
+ // Tweaked to commands to start without a space only if char before is a non-word character
+ // https://github.com/ichord/At.js
+ const atSymbolsWithBar = Object.keys(controllers).join('|');
+ const atSymbolsWithoutBar = Object.keys(controllers).join('');
+ const targetSubtext = subtext.split(GfmAutoComplete.regexSubtext).pop();
+ const resultantFlag = flag.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
+
+ const accentAChar = decodeURI('%C3%80');
+ const accentYChar = decodeURI('%C3%BF');
+
+ const regexp = new RegExp(`^(?:\\B|[^a-zA-Z0-9_${atSymbolsWithoutBar}]|\\s)${resultantFlag}(?!${atSymbolsWithBar})((?:[A-Za-z${accentAChar}-${accentYChar}0-9_'.+-]|[^\\x00-\\x7a])*)$`, 'gi');
+
+ return regexp.exec(targetSubtext);
+ }
}
+GfmAutoComplete.regexSubtext = new RegExp(/\s+/g);
+
GfmAutoComplete.defaultLoadingData = ['loading'];
GfmAutoComplete.atTypeMap = {