debian-mirror-gitlab/app/assets/javascripts/project_find_file.js

180 lines
5.3 KiB
JavaScript
Raw Normal View History

2019-12-26 22:10:19 +05:30
/* eslint-disable func-names, consistent-return, no-return-assign */
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
import fuzzaldrinPlus from 'fuzzaldrin-plus';
2021-03-11 19:13:27 +05:30
import $ from 'jquery';
import { deprecatedCreateFlash as flash } from '~/flash';
2021-01-03 14:25:43 +05:30
import { sanitize } from '~/lib/dompurify';
2018-03-17 18:26:18 +05:30
import axios from '~/lib/utils/axios_utils';
2021-01-03 14:25:43 +05:30
import { spriteIcon } from '~/lib/utils/common_utils';
2021-03-11 19:13:27 +05:30
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
2018-03-17 18:26:18 +05:30
import { __ } from '~/locale';
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
// highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
2021-03-08 18:12:59 +05:30
const highlighter = function (element, text, matches) {
2019-12-26 22:10:19 +05:30
let j = 0;
let len = 0;
let lastIndex = 0;
let matchedChars = [];
let matchIndex = matches[j];
let unmatched = text.substring(lastIndex, matchIndex);
2018-03-17 18:26:18 +05:30
for (j = 0, len = matches.length; j < len; j += 1) {
matchIndex = matches[j];
unmatched = text.substring(lastIndex, matchIndex);
if (unmatched) {
if (matchedChars.length) {
2018-12-13 13:39:08 +05:30
element.append(matchedChars.join('').bold());
2018-03-17 18:26:18 +05:30
}
matchedChars = [];
element.append(document.createTextNode(unmatched));
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
matchedChars.push(text[matchIndex]);
lastIndex = matchIndex + 1;
}
if (matchedChars.length) {
2018-12-13 13:39:08 +05:30
element.append(matchedChars.join('').bold());
2018-03-17 18:26:18 +05:30
}
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 = {};
2018-12-13 13:39:08 +05:30
this.inputElement = this.element.find('.file-finder-input');
2018-03-17 18:26:18 +05:30
// init event
this.initEvent();
// focus text input box
this.inputElement.focus();
// load file list
this.load(this.options.url);
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
initEvent() {
2021-02-22 17:27:13 +05:30
// eslint-disable-next-line @gitlab/no-global-event-off
2018-12-13 13:39:08 +05:30
this.inputElement.off('keyup');
2021-03-08 18:12:59 +05:30
this.inputElement.on('keyup', (event) => {
2020-03-13 15:44:24 +05:30
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();
2021-03-08 18:12:59 +05:30
return this.element.find('tr.tree-item').eq(0).addClass('selected').focus();
2020-03-13 15:44:24 +05:30
}
});
2018-03-17 18:26:18 +05:30
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
findFile() {
2019-12-26 22:10:19 +05:30
const searchText = sanitize(this.inputElement.val());
const result =
2018-12-13 13:39:08 +05:30
searchText.length > 0 ? fuzzaldrinPlus.filter(this.filePaths, searchText) : this.filePaths;
2018-03-17 18:26:18 +05:30
return this.renderList(result, searchText);
2018-12-13 13:39:08 +05:30
// find file
2018-03-17 18:26:18 +05:30
}
2016-09-13 17:45:13 +05:30
2019-12-21 20:55:43 +05:30
// files paths load
2018-03-17 18:26:18 +05:30
load(url) {
2018-12-13 13:39:08 +05:30
axios
.get(url)
2018-03-17 18:26:18 +05:30
.then(({ data }) => {
this.element.find('.loading').hide();
this.filePaths = data;
this.findFile();
2021-03-08 18:12:59 +05:30
this.element.find('.files-slider tr.tree-item').eq(0).addClass('selected').focus();
2018-03-17 18:26:18 +05:30
})
.catch(() => flash(__('An error occurred while loading filenames')));
}
2016-09-13 17:45:13 +05:30
2018-03-27 19:54:05 +05:30
// render result
2018-03-17 18:26:18 +05:30
renderList(filePaths, searchText) {
2019-12-26 22:10:19 +05:30
let i = 0;
let len = 0;
let matches = [];
const results = [];
2018-12-13 13:39:08 +05:30
this.element.find('.tree-table > tbody').empty();
2018-11-08 19:23:39 +05:30
for (i = 0, len = filePaths.length; i < len; i += 1) {
2019-12-26 22:10:19 +05:30
const filePath = filePaths[i];
2018-03-17 18:26:18 +05:30
if (i === 20) {
break;
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
if (searchText) {
matches = fuzzaldrinPlus.match(filePath, searchText);
2016-09-13 17:45:13 +05:30
}
2020-01-01 13:55:28 +05:30
const blobItemUrl = joinPaths(this.options.blobUrlTemplate, escapeFileUrl(filePath));
2019-12-26 22:10:19 +05:30
const html = ProjectFindFile.makeHtml(filePath, matches, blobItemUrl);
2018-12-13 13:39:08 +05:30
results.push(this.element.find('.tree-table > tbody').append(html));
2018-03-17 18:26:18 +05:30
}
2019-12-21 20:55:43 +05:30
this.element.find('.empty-state').toggleClass('hidden', Boolean(results.length));
2018-03-17 18:26:18 +05:30
return results;
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
// make tbody row html
static makeHtml(filePath, matches, blobItemUrl) {
2019-12-26 22:10:19 +05:30
const $tr = $(
2021-01-03 14:25:43 +05:30
`<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>`,
2018-12-13 13:39:08 +05:30
);
2018-03-17 18:26:18 +05:30
if (matches) {
2018-12-13 13:39:08 +05:30
$tr
.find('a')
.replaceWith(highlighter($tr.find('a'), filePath, matches).attr('href', blobItemUrl));
2018-03-17 18:26:18 +05:30
} else {
2018-12-13 13:39:08 +05:30
$tr.find('a').attr('href', blobItemUrl);
$tr.find('.str-truncated').text(filePath);
2018-03-17 18:26:18 +05:30
}
return $tr;
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
selectRow(type) {
2019-12-26 22:10:19 +05:30
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();
2018-03-17 18:26:18 +05:30
if (rows && rows.length > 0) {
if (selectedRow && selectedRow.length > 0) {
2018-12-13 13:39:08 +05:30
if (type === 'UP') {
2018-03-17 18:26:18 +05:30
next = selectedRow.prev();
2018-12-13 13:39:08 +05:30
} else if (type === 'DOWN') {
2018-03-17 18:26:18 +05:30
next = selectedRow.next();
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
if (next.length > 0) {
2018-12-13 13:39:08 +05:30
selectedRow.removeClass('selected');
2018-03-17 18:26:18 +05:30
selectedRow = next;
}
} else {
selectedRow = rows.eq(0);
2016-09-13 17:45:13 +05:30
}
2018-12-13 13:39:08 +05:30
return selectedRow.addClass('selected').focus();
2018-03-17 18:26:18 +05:30
}
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
selectRowUp() {
2018-12-13 13:39:08 +05:30
return this.selectRow('UP');
2018-03-17 18:26:18 +05:30
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
selectRowDown() {
2018-12-13 13:39:08 +05:30
return this.selectRow('DOWN');
2018-03-17 18:26:18 +05:30
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
goToTree() {
2018-12-13 13:39:08 +05:30
return (window.location.href = this.options.treeUrl);
2018-03-17 18:26:18 +05:30
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
goToBlob() {
2019-12-26 22:10:19 +05:30
const $link = this.element.find('.tree-item.selected .tree-item-file-name a');
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
if ($link.length) {
$link.get(0).click();
}
}
}