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:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
commitedaa33dee2ff2f7ea3fac488d41558eb5f86d68c (patch)
tree11f143effbfeba52329fb7afbd05e6e2a3790241 /app/assets/javascripts/projects/project_find_file.js
parentd8a5691316400a0f7ec4f83832698f1988eb27c1 (diff)
Add latest changes from gitlab-org/gitlab@14-7-stable-eev14.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/projects/project_find_file.js')
-rw-r--r--app/assets/javascripts/projects/project_find_file.js183
1 files changed, 183 insertions, 0 deletions
diff --git a/app/assets/javascripts/projects/project_find_file.js b/app/assets/javascripts/projects/project_find_file.js
new file mode 100644
index 00000000000..d295c06928f
--- /dev/null
+++ b/app/assets/javascripts/projects/project_find_file.js
@@ -0,0 +1,183 @@
+/* eslint-disable func-names, consistent-return, no-return-assign */
+
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import $ from 'jquery';
+import createFlash from '~/flash';
+import { sanitize } from '~/lib/dompurify';
+import axios from '~/lib/utils/axios_utils';
+import { spriteIcon } from '~/lib/utils/common_utils';
+import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
+
+// highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
+const highlighter = function (element, text, matches) {
+ let j = 0;
+ let len = 0;
+ let lastIndex = 0;
+ let matchedChars = [];
+ let matchIndex = matches[j];
+ let unmatched = text.substring(lastIndex, matchIndex);
+ for (j = 0, len = matches.length; j < len; j += 1) {
+ matchIndex = matches[j];
+ unmatched = text.substring(lastIndex, matchIndex);
+ if (unmatched) {
+ if (matchedChars.length) {
+ element.append(matchedChars.join('').bold());
+ }
+ matchedChars = [];
+ element.append(document.createTextNode(unmatched));
+ }
+ matchedChars.push(text[matchIndex]);
+ lastIndex = matchIndex + 1;
+ }
+ if (matchedChars.length) {
+ element.append(matchedChars.join('').bold());
+ }
+ return element.append(document.createTextNode(text.substring(lastIndex)));
+};
+
+export default class ProjectFindFile {
+ constructor(element1, options) {
+ this.element = element1;
+ this.options = options;
+ this.goToBlob = this.goToBlob.bind(this);
+ this.goToTree = this.goToTree.bind(this);
+ this.selectRowDown = this.selectRowDown.bind(this);
+ this.selectRowUp = this.selectRowUp.bind(this);
+ this.filePaths = {};
+ this.inputElement = this.element.find('.file-finder-input');
+ // init event
+ this.initEvent();
+ // focus text input box
+ this.inputElement.focus();
+ // load file list
+ this.load(this.options.url);
+ }
+
+ initEvent() {
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.inputElement.off('keyup');
+ this.inputElement.on('keyup', (event) => {
+ const target = $(event.target);
+ const value = target.val();
+ const ref = target.data('oldValue');
+ const oldValue = ref != null ? ref : '';
+ if (value !== oldValue) {
+ target.data('oldValue', value);
+ this.findFile();
+ return this.element.find('tr.tree-item').eq(0).addClass('selected').focus();
+ }
+ });
+ }
+
+ findFile() {
+ const searchText = sanitize(this.inputElement.val());
+ const result =
+ searchText.length > 0 ? fuzzaldrinPlus.filter(this.filePaths, searchText) : this.filePaths;
+ return this.renderList(result, searchText);
+ // find file
+ }
+
+ // files paths load
+ load(url) {
+ axios
+ .get(url)
+ .then(({ data }) => {
+ this.element.find('.loading').hide();
+ this.filePaths = data;
+ this.findFile();
+ this.element.find('.files-slider tr.tree-item').eq(0).addClass('selected').focus();
+ })
+ .catch(() =>
+ createFlash({
+ message: __('An error occurred while loading filenames'),
+ }),
+ );
+ }
+
+ // render result
+ renderList(filePaths, searchText) {
+ let i = 0;
+ let len = 0;
+ let matches = [];
+ const results = [];
+ this.element.find('.tree-table > tbody').empty();
+ for (i = 0, len = filePaths.length; i < len; i += 1) {
+ const filePath = filePaths[i];
+ if (i === 20) {
+ break;
+ }
+ if (searchText) {
+ matches = fuzzaldrinPlus.match(filePath, searchText);
+ }
+ const blobItemUrl = joinPaths(this.options.blobUrlTemplate, escapeFileUrl(filePath));
+ const html = ProjectFindFile.makeHtml(filePath, matches, blobItemUrl);
+ results.push(this.element.find('.tree-table > tbody').append(html));
+ }
+
+ this.element.find('.empty-state').toggleClass('hidden', Boolean(results.length));
+
+ return results;
+ }
+
+ // make tbody row html
+ static makeHtml(filePath, matches, blobItemUrl) {
+ const $tr = $(
+ `<tr class='tree-item'><td class='tree-item-file-name link-container'><a>${spriteIcon(
+ 'doc-text',
+ 's16 vertical-align-middle gl-mr-1',
+ )}<span class='str-truncated'></span></a></td></tr>`,
+ );
+ if (matches) {
+ $tr
+ .find('a')
+ .replaceWith(highlighter($tr.find('a'), filePath, matches).attr('href', blobItemUrl));
+ } else {
+ $tr.find('a').attr('href', blobItemUrl);
+ $tr.find('.str-truncated').text(filePath);
+ }
+ return $tr;
+ }
+
+ selectRow(type) {
+ const rows = this.element.find('.files-slider tr.tree-item');
+ let selectedRow = this.element.find('.files-slider tr.tree-item.selected');
+ let next = selectedRow.prev();
+ if (rows && rows.length > 0) {
+ if (selectedRow && selectedRow.length > 0) {
+ if (type === 'UP') {
+ next = selectedRow.prev();
+ } else if (type === 'DOWN') {
+ next = selectedRow.next();
+ }
+ if (next.length > 0) {
+ selectedRow.removeClass('selected');
+ selectedRow = next;
+ }
+ } else {
+ selectedRow = rows.eq(0);
+ }
+ return selectedRow.addClass('selected').focus();
+ }
+ }
+
+ selectRowUp() {
+ return this.selectRow('UP');
+ }
+
+ selectRowDown() {
+ return this.selectRow('DOWN');
+ }
+
+ goToTree() {
+ return (window.location.href = this.options.treeUrl);
+ }
+
+ goToBlob() {
+ const $link = this.element.find('.tree-item.selected .tree-item-file-name a');
+
+ if ($link.length) {
+ $link.get(0).click();
+ }
+ }
+}