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
parentd8a5691316400a0f7ec4f83832698f1988eb27c1 (diff)
Add latest changes from gitlab-org/gitlab@14-7-stable-eev14.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/projects')
-rw-r--r--app/assets/javascripts/projects/project_find_file.js183
-rw-r--r--app/assets/javascripts/projects/project_import.js7
-rw-r--r--app/assets/javascripts/projects/project_visibility.js71
-rw-r--r--app/assets/javascripts/projects/star.js38
4 files changed, 299 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();
+ }
+ }
+}
diff --git a/app/assets/javascripts/projects/project_import.js b/app/assets/javascripts/projects/project_import.js
new file mode 100644
index 00000000000..27a218f1f52
--- /dev/null
+++ b/app/assets/javascripts/projects/project_import.js
@@ -0,0 +1,7 @@
+import { visitUrl } from '~/lib/utils/url_utility';
+
+export default function projectImport() {
+ setTimeout(() => {
+ visitUrl(window.location.href);
+ }, 5000);
+}
diff --git a/app/assets/javascripts/projects/project_visibility.js b/app/assets/javascripts/projects/project_visibility.js
new file mode 100644
index 00000000000..c962554c9f4
--- /dev/null
+++ b/app/assets/javascripts/projects/project_visibility.js
@@ -0,0 +1,71 @@
+import $ from 'jquery';
+import { escape } from 'lodash';
+import { __, sprintf } from '~/locale';
+import eventHub from '~/projects/new/event_hub';
+
+// Values are from lib/gitlab/visibility_level.rb
+const visibilityLevel = {
+ private: 0,
+ internal: 10,
+ public: 20,
+};
+
+function setVisibilityOptions({ name, visibility, showPath, editPath }) {
+ document.querySelectorAll('.visibility-level-setting .form-check').forEach((option) => {
+ // Don't change anything if the option is restricted by admin
+ if (option.classList.contains('restricted')) {
+ return;
+ }
+
+ const optionInput = option.querySelector('input[type=radio]');
+ const optionValue = optionInput ? parseInt(optionInput.value, 10) : 0;
+
+ if (visibilityLevel[visibility] < optionValue) {
+ option.classList.add('disabled');
+ optionInput.disabled = true;
+ const reason = option.querySelector('.option-disabled-reason');
+ if (reason) {
+ const optionTitle = option.querySelector('.option-title');
+ const optionName = optionTitle ? optionTitle.innerText.toLowerCase() : '';
+ reason.innerHTML = sprintf(
+ __(
+ 'This project cannot be %{visibilityLevel} because the visibility of %{openShowLink}%{name}%{closeShowLink} is %{visibility}. To make this project %{visibilityLevel}, you must first %{openEditLink}change the visibility%{closeEditLink} of the parent group.',
+ ),
+ {
+ visibilityLevel: optionName,
+ name: escape(name),
+ visibility,
+ openShowLink: `<a href="${showPath}">`,
+ closeShowLink: '</a>',
+ openEditLink: `<a href="${editPath}">`,
+ closeEditLink: '</a>',
+ },
+ false,
+ );
+ }
+ } else {
+ option.classList.remove('disabled');
+ optionInput.disabled = false;
+ }
+ });
+}
+
+function handleSelect2DropdownChange(namespaceSelector) {
+ if (!namespaceSelector || !('selectedIndex' in namespaceSelector)) {
+ return;
+ }
+ const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex];
+ setVisibilityOptions(selectedNamespace.dataset);
+}
+
+export default function initProjectVisibilitySelector() {
+ eventHub.$on('update-visibility', setVisibilityOptions);
+
+ const namespaceSelector = document.querySelector('select.js-select-namespace');
+ if (namespaceSelector) {
+ $('.select2.js-select-namespace').on('change', () =>
+ handleSelect2DropdownChange(namespaceSelector),
+ );
+ handleSelect2DropdownChange(namespaceSelector);
+ }
+}
diff --git a/app/assets/javascripts/projects/star.js b/app/assets/javascripts/projects/star.js
new file mode 100644
index 00000000000..578e22ca25d
--- /dev/null
+++ b/app/assets/javascripts/projects/star.js
@@ -0,0 +1,38 @@
+import $ from 'jquery';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { spriteIcon } from '~/lib/utils/common_utils';
+import { __, s__ } from '~/locale';
+
+export default class Star {
+ constructor(container = '.project-home-panel') {
+ $(`${container} .toggle-star`).on('click', function toggleStarClickCallback() {
+ const $this = $(this);
+ const $starSpan = $this.find('span');
+ const $starIcon = $this.find('svg');
+ const iconClasses = $starIcon.attr('class').split(' ');
+
+ axios
+ .post($this.data('endpoint'))
+ .then(({ data }) => {
+ const isStarred = $starSpan.hasClass('starred');
+ $this.parent().find('.count').text(data.star_count);
+
+ if (isStarred) {
+ $starSpan.removeClass('starred').text(s__('StarProject|Star'));
+ $starIcon.remove();
+ $this.prepend(spriteIcon('star-o', iconClasses));
+ } else {
+ $starSpan.addClass('starred').text(__('Unstar'));
+ $starIcon.remove();
+ $this.prepend(spriteIcon('star', iconClasses));
+ }
+ })
+ .catch(() =>
+ createFlash({
+ message: __('Star toggle failed. Try again later.'),
+ }),
+ );
+ });
+ }
+}