Commit 6a1b84c7 authored by Filipa Lacerda's avatar Filipa Lacerda

Use modules in common utils

parent 5d952f75
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global Flash */ /* global Flash */
import _ from 'underscore'; import _ from 'underscore';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { isInIssuePage, updateTooltipTitle } from './lib/utils/common_utils';
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'; const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
...@@ -237,7 +238,7 @@ class AwardsHandler { ...@@ -237,7 +238,7 @@ class AwardsHandler {
addAward(votesBlock, awardUrl, emoji, checkMutuality, callback) { addAward(votesBlock, awardUrl, emoji, checkMutuality, callback) {
const isMainAwardsBlock = votesBlock.closest('.js-issue-note-awards').length; const isMainAwardsBlock = votesBlock.closest('.js-issue-note-awards').length;
if (gl.utils.isInIssuePage() && !isMainAwardsBlock) { if (isInIssuePage() && !isMainAwardsBlock) {
const id = votesBlock.attr('id').replace('note_', ''); const id = votesBlock.attr('id').replace('note_', '');
$('.emoji-menu').removeClass('is-visible'); $('.emoji-menu').removeClass('is-visible');
...@@ -288,7 +289,7 @@ class AwardsHandler { ...@@ -288,7 +289,7 @@ class AwardsHandler {
} }
getVotesBlock() { getVotesBlock() {
if (gl.utils.isInIssuePage()) { if (isInIssuePage()) {
const $el = $('.js-add-award.is-active').closest('.note.timeline-entry'); const $el = $('.js-add-award.is-active').closest('.note.timeline-entry');
if ($el.length) { if ($el.length) {
...@@ -452,11 +453,11 @@ class AwardsHandler { ...@@ -452,11 +453,11 @@ class AwardsHandler {
userAuthored($emojiButton) { userAuthored($emojiButton) {
const oldTitle = this.getAwardTooltip($emojiButton); const oldTitle = this.getAwardTooltip($emojiButton);
const newTitle = 'You cannot vote on your own issue, MR and note'; const newTitle = 'You cannot vote on your own issue, MR and note';
gl.utils.updateTooltipTitle($emojiButton, newTitle).tooltip('show'); updateTooltipTitle($emojiButton, newTitle).tooltip('show');
// Restore tooltip back to award list // Restore tooltip back to award list
return setTimeout(() => { return setTimeout(() => {
$emojiButton.tooltip('hide'); $emojiButton.tooltip('hide');
gl.utils.updateTooltipTitle($emojiButton, oldTitle); updateTooltipTitle($emojiButton, oldTitle);
}, 2800); }, 2800);
} }
......
import '../commons/bootstrap'; import '../commons/bootstrap';
import { isInIssuePage } from '../lib/utils/common_utils';
// Quick Submit behavior // Quick Submit behavior
// //
...@@ -45,7 +46,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => { ...@@ -45,7 +46,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
if (!$submitButton.attr('disabled')) { if (!$submitButton.attr('disabled')) {
$submitButton.trigger('click', [e]); $submitButton.trigger('click', [e]);
if (!gl.utils.isInIssuePage()) { if (!isInIssuePage()) {
$submitButton.disable(); $submitButton.disable();
} }
} }
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, camelcase, one-var-declaration-per-line, no-else-return, max-len */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, camelcase, one-var-declaration-per-line, no-else-return, max-len */
import { rstrip } from './lib/utils/common_utils';
window.ConfirmDangerModal = (function() { window.ConfirmDangerModal = (function() {
function ConfirmDangerModal(form, text) { function ConfirmDangerModal(form, text) {
...@@ -12,7 +13,7 @@ window.ConfirmDangerModal = (function() { ...@@ -12,7 +13,7 @@ window.ConfirmDangerModal = (function() {
submit.disable(); submit.disable();
$('.js-confirm-danger-input').off('input'); $('.js-confirm-danger-input').off('input');
$('.js-confirm-danger-input').on('input', function() { $('.js-confirm-danger-input').on('input', function() {
if (gl.utils.rstrip($(this).val()) === project_path) { if (rstrip($(this).val()) === project_path) {
return submit.enable(); return submit.enable();
} else { } else {
return submit.disable(); return submit.disable();
......
...@@ -77,6 +77,7 @@ import initProjectVisibilitySelector from './project_visibility'; ...@@ -77,6 +77,7 @@ import initProjectVisibilitySelector from './project_visibility';
import GpgBadges from './gpg_badges'; import GpgBadges from './gpg_badges';
import UserFeatureHelper from './helpers/user_feature_helper'; import UserFeatureHelper from './helpers/user_feature_helper';
import initChangesDropdown from './init_changes_dropdown'; import initChangesDropdown from './init_changes_dropdown';
import { ajaxGet } from './lib/utils/common_utils';
(function() { (function() {
var Dispatcher; var Dispatcher;
...@@ -351,7 +352,7 @@ import initChangesDropdown from './init_changes_dropdown'; ...@@ -351,7 +352,7 @@ import initChangesDropdown from './init_changes_dropdown';
if ($('.blob-viewer').length) new BlobViewer(); if ($('.blob-viewer').length) new BlobViewer();
if ($('.project-show-activity').length) new gl.Activities(); if ($('.project-show-activity').length) new gl.Activities();
$('#tree-slider').waitForImages(function() { $('#tree-slider').waitForImages(function() {
gl.utils.ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath); ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
}); });
break; break;
case 'projects:edit': case 'projects:edit':
...@@ -427,7 +428,7 @@ import initChangesDropdown from './init_changes_dropdown'; ...@@ -427,7 +428,7 @@ import initChangesDropdown from './init_changes_dropdown';
new NewCommitForm($('.js-create-dir-form')); new NewCommitForm($('.js-create-dir-form'));
new UserCallout({ setCalloutPerProject: true }); new UserCallout({ setCalloutPerProject: true });
$('#tree-slider').waitForImages(function() { $('#tree-slider').waitForImages(function() {
gl.utils.ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath); ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
}); });
break; break;
case 'projects:find_file:show': case 'projects:find_file:show':
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-param-reassign, no-else-return, quotes, object-shorthand, comma-dangle, camelcase, one-var, vars-on-top, one-var-declaration-per-line, no-return-assign, consistent-return, max-len, prefer-template */ /* eslint-disable no-param-reassing */
(function() {
(function(w) { export const getPagePath = (index = 0) => $('body').data('page').split(':')[index];
var base; window.gl.utils.getPagePath = getPagePath;
const faviconEl = document.getElementById('favicon');
const originalFavicon = faviconEl ? faviconEl.getAttribute('href') : null; export const isInGroupsPage = () => getPagePath() === 'groups';
w.gl || (w.gl = {}); window.gl.utils.isInGroupsPage = isInGroupsPage;
(base = w.gl).utils || (base.utils = {});
w.gl.utils.isInGroupsPage = function() { export const isInProjectPage = () => getPagePath() === 'projects';
return gl.utils.getPagePath() === 'groups'; window.gl.utils.isInProjectPage = isInProjectPage;
};
w.gl.utils.isInProjectPage = function() { export const getProjectSlug = () => {
return gl.utils.getPagePath() === 'projects'; if (isInProjectPage()) {
};
w.gl.utils.getProjectSlug = function() {
if (this.isInProjectPage()) {
return $('body').data('project'); return $('body').data('project');
} else {
return null;
} }
};
w.gl.utils.getGroupSlug = function() {
if (this.isInGroupsPage()) {
return $('body').data('group');
} else {
return null; return null;
};
window.gl.utils.getProjectSlug = getProjectSlug;
export const getGroupSlug = () => {
if (isInGroupsPage()) {
return $('body').data('group');
} }
}; return null;
};
window.gl.utils.getGroupSlug = getGroupSlug;
w.gl.utils.isInIssuePage = () => { export const isInIssuePage = () => {
const page = gl.utils.getPagePath(1); const page = getPagePath(1);
const action = gl.utils.getPagePath(2); const action = getPagePath(2);
return page === 'issues' && action === 'show'; return page === 'issues' && action === 'show';
}; };
window.gl.utils.isInIssuePage = isInGroupsPage;
w.gl.utils.ajaxGet = function(url) { window.gl.utils.ajaxGet = url => $.ajax({
return $.ajax({ type: 'GET',
type: "GET", url,
url: url, dataType: 'script',
dataType: "script" });
}); export const ajaxGet = window.gl.utils.ajaxGet;
};
w.gl.utils.ajaxPost = function(url, data) { export const ajaxPost = (url, data) => $.ajax({
return $.ajax({
type: 'POST', type: 'POST',
url: url, url,
data: data, data,
}); });
}; window.gl.utils.ajaxPost = ajaxPost;
w.gl.utils.extractLast = function(term) { // TODO: This function seems not to be used anywhere
return this.split(term).pop(); window.gl.utils.extractLast = term => this.split(term).pop();
};
w.gl.utils.rstrip = function rstrip(val) { export const rstrip = function rstrip(val) {
if (val) { if (val) {
return val.replace(/\s+$/, ''); return val.replace(/\s+$/, '');
} else {
return val;
} }
}; return val;
};
window.gl.utils.rstrip = rstrip;
gl.utils.updateTooltipTitle = function($tooltipEl, newTitle) { export const updateTooltipTitle = ($tooltipEl, newTitle) => $tooltipEl.attr('title', newTitle).tooltip('fixTitle');
return $tooltipEl.attr('title', newTitle).tooltip('fixTitle'); window.gl.utils.updateTooltipTitle = updateTooltipTitle;
};
w.gl.utils.disableButtonIfEmptyField = function(field_selector, button_selector, event_name) { export const disableButtonIfEmptyField = (fieldSelector, buttonSelector, eventName = 'input') => {
event_name = event_name || 'input'; const field = $(fieldSelector);
var closest_submit, field, that; const closestSubmit = field.closest('form').find(buttonSelector);
that = this; if (rstrip(field.val()) === '') {
field = $(field_selector); closestSubmit.disable();
closest_submit = field.closest('form').find(button_selector);
if (this.rstrip(field.val()) === "") {
closest_submit.disable();
} }
return field.on(event_name, function() { return field.on(eventName, () => {
if (that.rstrip($(this).val()) === "") { if (rstrip($(this).val()) === '') {
return closest_submit.disable(); return closestSubmit.disable();
} else {
return closest_submit.enable();
} }
return closestSubmit.enable();
}); });
}; };
window.gl.utils.disableButtonIfEmptyField = disableButtonIfEmptyField;
// automatically adjust scroll position for hash urls taking the height of the navbar into account // automatically adjust scroll position for hash urls taking the height of the navbar into account
// https://github.com/twitter/bootstrap/issues/1768 // https://github.com/twitter/bootstrap/issues/1768
w.gl.utils.handleLocationHash = function() { export const handleLocationHash = () => {
var hash = w.gl.utils.getLocationHash(); let hash = window.gl.utils.getLocationHash();
if (!hash) return; if (!hash) return;
// This is required to handle non-unicode characters in hash // This is required to handle non-unicode characters in hash
...@@ -97,12 +89,12 @@ ...@@ -97,12 +89,12 @@
const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck'); const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck');
const fixedNav = document.querySelector('.navbar-gitlab'); const fixedNav = document.querySelector('.navbar-gitlab');
var adjustment = 0; let adjustment = 0;
if (fixedNav) adjustment -= fixedNav.offsetHeight; if (fixedNav) adjustment -= fixedNav.offsetHeight;
// scroll to user-generated markdown anchor if we cannot find a match // scroll to user-generated markdown anchor if we cannot find a match
if (document.getElementById(hash) === null) { if (document.getElementById(hash) === null) {
var target = document.getElementById('user-content-' + hash); const target = document.getElementById(`user-content-${hash}`);
if (target && target.scrollIntoView) { if (target && target.scrollIntoView) {
target.scrollIntoView(true); target.scrollIntoView(true);
window.scrollBy(0, adjustment); window.scrollBy(0, adjustment);
...@@ -119,12 +111,13 @@ ...@@ -119,12 +111,13 @@
window.scrollBy(0, adjustment); window.scrollBy(0, adjustment);
} }
}; };
window.gl.utils.handleLocationHash = handleLocationHash;
// Check if element scrolled into viewport from above or below // Check if element scrolled into viewport from above or below
// Courtesy http://stackoverflow.com/a/7557433/414749 // Courtesy http://stackoverflow.com/a/7557433/414749
w.gl.utils.isInViewport = function(el) { export const isInViewport = (el) => {
var rect = el.getBoundingClientRect(); const rect = el.getBoundingClientRect();
return ( return (
rect.top >= 0 && rect.top >= 0 &&
...@@ -132,48 +125,42 @@ ...@@ -132,48 +125,42 @@
rect.bottom <= window.innerHeight && rect.bottom <= window.innerHeight &&
rect.right <= window.innerWidth rect.right <= window.innerWidth
); );
}; };
window.gl.utils.isInViewport = isInViewport;
gl.utils.getPagePath = function(index) {
index = index || 0;
return $('body').data('page').split(':')[index];
};
gl.utils.parseUrl = function (url) { export const parseUrl = (url) => {
var parser = document.createElement('a'); const parser = document.createElement('a');
parser.href = url; parser.href = url;
return parser; return parser;
}; };
window.gl.utils.parseUrl = parseUrl;
gl.utils.parseUrlPathname = function (url) { export const parseUrlPathname = (url) => {
var parsedUrl = gl.utils.parseUrl(url); const parsedUrl = parseUrl(url);
// parsedUrl.pathname will return an absolute path for Firefox and a relative path for IE11 // parsedUrl.pathname will return an absolute path for Firefox and a relative path for IE11
// We have to make sure we always have an absolute path. // We have to make sure we always have an absolute path.
return parsedUrl.pathname.charAt(0) === '/' ? parsedUrl.pathname : '/' + parsedUrl.pathname; return parsedUrl.pathname.charAt(0) === '/' ? parsedUrl.pathname : `/${parsedUrl.pathname}`;
}; };
window.gl.utils.parseUrlPathname = parseUrlPathname;
gl.utils.getUrlParamsArray = function () { // We can trust that each param has one & since values containing & will be encoded
// We can trust that each param has one & since values containing & will be encoded // Remove the first character of search as it is always ?
// Remove the first character of search as it is always ? window.gl.utils.getUrlParamsArray = () => window.location.search.slice(1).split('&').map((param) => {
return window.location.search.slice(1).split('&').map((param) => {
const split = param.split('='); const split = param.split('=');
return [decodeURI(split[0]), split[1]].join('='); return [decodeURI(split[0]), split[1]].join('=');
}); });
};
gl.utils.isMetaKey = function(e) { export const isMetaKey = e => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey; window.gl.utils.isMetaKey = isMetaKey;
};
gl.utils.isMetaClick = function(e) { // Identify following special clicks
// Identify following special clicks // 1) Cmd + Click on Mac (e.metaKey)
// 1) Cmd + Click on Mac (e.metaKey) // 2) Ctrl + Click on PC (e.ctrlKey)
// 2) Ctrl + Click on PC (e.ctrlKey) // 3) Middle-click or Mouse Wheel Click (e.which is 2)
// 3) Middle-click or Mouse Wheel Click (e.which is 2) export const isMetaClick = e => e.metaKey || e.ctrlKey || e.which === 2;
return e.metaKey || e.ctrlKey || e.which === 2; window.gl.utils.isMetaClick = isMetaClick;
};
gl.utils.scrollToElement = function($el) { export const scrollToElement = ($el) => {
const top = $el.offset().top; const top = $el.offset().top;
const mrTabsHeight = $('.merge-request-tabs').height() || 0; const mrTabsHeight = $('.merge-request-tabs').height() || 0;
const headerHeight = $('.navbar-gitlab').height() || 0; const headerHeight = $('.navbar-gitlab').height() || 0;
...@@ -181,24 +168,26 @@ ...@@ -181,24 +168,26 @@
return $('body, html').animate({ return $('body, html').animate({
scrollTop: top - mrTabsHeight - headerHeight, scrollTop: top - mrTabsHeight - headerHeight,
}, 200); }, 200);
}; };
window.gl.utils.scrollToElement = scrollToElement;
/** /**
this will take in the `name` of the param you want to parse in the url this will take in the `name` of the param you want to parse in the url
if the name does not exist this function will return `null` if the name does not exist this function will return `null`
otherwise it will return the value of the param key provided otherwise it will return the value of the param key provided
*/ */
w.gl.utils.getParameterByName = (name, parseUrl) => { export const getParameterByName = (name, urlToParse) => {
const url = parseUrl || window.location.href; const url = urlToParse || window.location.href;
name = name.replace(/[[\]]/g, '\\$&'); name = name.replace(/[[\]]/g, '\\$&');
const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`);
const results = regex.exec(url); const results = regex.exec(url);
if (!results) return null; if (!results) return null;
if (!results[2]) return ''; if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' ')); return decodeURIComponent(results[2].replace(/\+/g, ' '));
}; };
window.gl.utils.getParameterByName = getParameterByName;
w.gl.utils.getSelectedFragment = () => { export const getSelectedFragment = () => {
const selection = window.getSelection(); const selection = window.getSelection();
if (selection.rangeCount === 0) return null; if (selection.rangeCount === 0) return null;
const documentFragment = document.createDocumentFragment(); const documentFragment = document.createDocumentFragment();
...@@ -208,11 +197,11 @@ ...@@ -208,11 +197,11 @@
if (documentFragment.textContent.length === 0) return null; if (documentFragment.textContent.length === 0) return null;
return documentFragment; return documentFragment;
}; };
window.gl.utils.getSelectedFragment = getSelectedFragment;
w.gl.utils.insertText = (target, text) => { export const insertText = (target, text) => {
// Firefox doesn't support `document.execCommand('insertText', false, text)` on textareas // Firefox doesn't support `document.execCommand('insertText', false, text)` on textareas
const selectionStart = target.selectionStart; const selectionStart = target.selectionStart;
const selectionEnd = target.selectionEnd; const selectionEnd = target.selectionEnd;
const value = target.value; const value = target.value;
...@@ -230,12 +219,13 @@ ...@@ -230,12 +219,13 @@
$(target).trigger('input'); $(target).trigger('input');
// Trigger autosize // Trigger autosize
var event = document.createEvent('Event'); const event = document.createEvent('Event');
event.initEvent('autosize:update', true, false); event.initEvent('autosize:update', true, false);
target.dispatchEvent(event); target.dispatchEvent(event);
}; };
window.gl.utils.insertText = insertText;
w.gl.utils.nodeMatchesSelector = (node, selector) => { export const nodeMatchesSelector = (node, selector) => {
const matches = Element.prototype.matches || const matches = Element.prototype.matches ||
Element.prototype.matchesSelector || Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector || Element.prototype.mozMatchesSelector ||
...@@ -258,13 +248,14 @@ ...@@ -258,13 +248,14 @@
const matchingNodes = parentNode.querySelectorAll(selector); const matchingNodes = parentNode.querySelectorAll(selector);
return Array.prototype.indexOf.call(matchingNodes, node) !== -1; return Array.prototype.indexOf.call(matchingNodes, node) !== -1;
}; };
window.gl.utils.nodeMatchesSelector = nodeMatchesSelector;
/** /**
this will take in the headers from an API response and normalize them this will take in the headers from an API response and normalize them
this way we don't run into production issues when nginx gives us lowercased header keys this way we don't run into production issues when nginx gives us lowercased header keys
*/ */
w.gl.utils.normalizeHeaders = (headers) => { export const normalizeHeaders = (headers) => {
const upperCaseHeaders = {}; const upperCaseHeaders = {};
Object.keys(headers).forEach((e) => { Object.keys(headers).forEach((e) => {
...@@ -272,13 +263,14 @@ ...@@ -272,13 +263,14 @@
}); });
return upperCaseHeaders; return upperCaseHeaders;
}; };
window.gl.utils.normalizeHeaders = normalizeHeaders;
/** /**
this will take in the getAllResponseHeaders result and normalize them this will take in the getAllResponseHeaders result and normalize them
this way we don't run into production issues when nginx gives us lowercased header keys this way we don't run into production issues when nginx gives us lowercased header keys
*/ */
w.gl.utils.normalizeCRLFHeaders = (headers) => { export const normalizeCRLFHeaders = (headers) => {
const headersObject = {}; const headersObject = {};
const headersArray = headers.split('\n'); const headersArray = headers.split('\n');
...@@ -287,25 +279,27 @@ ...@@ -287,25 +279,27 @@
headersObject[keyValue[0]] = keyValue[1]; headersObject[keyValue[0]] = keyValue[1];
}); });
return w.gl.utils.normalizeHeaders(headersObject); return normalizeHeaders(headersObject);
}; };
window.gl.utils.normalizeCRLFHeaders = normalizeCRLFHeaders;
/** /**
* Parses pagination object string values into numbers. * Parses pagination object string values into numbers.
* *
* @param {Object} paginationInformation * @param {Object} paginationInformation
* @returns {Object} * @returns {Object}
*/ */
w.gl.utils.parseIntPagination = paginationInformation => ({ export const parseIntPagination = paginationInformation => ({
perPage: parseInt(paginationInformation['X-PER-PAGE'], 10), perPage: parseInt(paginationInformation['X-PER-PAGE'], 10),
page: parseInt(paginationInformation['X-PAGE'], 10), page: parseInt(paginationInformation['X-PAGE'], 10),
total: parseInt(paginationInformation['X-TOTAL'], 10), total: parseInt(paginationInformation['X-TOTAL'], 10),
totalPages: parseInt(paginationInformation['X-TOTAL-PAGES'], 10), totalPages: parseInt(paginationInformation['X-TOTAL-PAGES'], 10),
nextPage: parseInt(paginationInformation['X-NEXT-PAGE'], 10), nextPage: parseInt(paginationInformation['X-NEXT-PAGE'], 10),
previousPage: parseInt(paginationInformation['X-PREV-PAGE'], 10), previousPage: parseInt(paginationInformation['X-PREV-PAGE'], 10),
}); });
window.gl.utils.parseIntPagination = parseIntPagination;
/** /**
* Updates the search parameter of a URL given the parameter and value provided. * Updates the search parameter of a URL given the parameter and value provided.
* *
* If no search params are present we'll add it. * If no search params are present we'll add it.
...@@ -317,7 +311,7 @@ ...@@ -317,7 +311,7 @@
* @param {Number|String|Undefined|Null} value * @param {Number|String|Undefined|Null} value
* @return {String} * @return {String}
*/ */
w.gl.utils.setParamInURL = (param, value) => { export const setParamInURL = (param, value) => {
let search; let search;
const locationSearch = window.location.search; const locationSearch = window.location.search;
...@@ -342,17 +336,19 @@ ...@@ -342,17 +336,19 @@
} }
return search; return search;
}; };
window.gl.utils.setParamInURL = setParamInURL;
/** /**
* Converts permission provided as strings to booleans. * Converts permission provided as strings to booleans.
* *
* @param {String} string * @param {String} string
* @returns {Boolean} * @returns {Boolean}
*/ */
w.gl.utils.convertPermissionToBoolean = permission => permission === 'true'; export const convertPermissionToBoolean = permission => permission === 'true';
window.gl.utils.convertPermissionToBoolean = convertPermissionToBoolean;
/** /**
* Back Off exponential algorithm * Back Off exponential algorithm
* backOff :: (Function<next, stop>, Number) -> Promise<Any, Error> * backOff :: (Function<next, stop>, Number) -> Promise<Any, Error>
* *
...@@ -383,7 +379,7 @@ ...@@ -383,7 +379,7 @@
* }) * })
* ``` * ```
*/ */
w.gl.utils.backOff = (fn, timeout = 60000) => { export const backOff = (fn, timeout = 60000) => {
const maxInterval = 32000; const maxInterval = 32000;
let nextInterval = 2000; let nextInterval = 2000;
let timeElapsed = 0; let timeElapsed = 0;
...@@ -403,35 +399,40 @@ ...@@ -403,35 +399,40 @@
fn(next, stop); fn(next, stop);
}); });
}; };
window.gl.utils.backOff = backOff;
w.gl.utils.setFavicon = (faviconPath) => { export const setFavicon = (faviconPath) => {
const faviconEl = document.getElementById('favicon');
if (faviconEl && faviconPath) { if (faviconEl && faviconPath) {
faviconEl.setAttribute('href', faviconPath); faviconEl.setAttribute('href', faviconPath);
} }
}; };
window.gl.utils.setFavicon = setFavicon;
w.gl.utils.resetFavicon = () => { export const resetFavicon = () => {
const faviconEl = document.getElementById('favicon');
const originalFavicon = faviconEl ? faviconEl.getAttribute('href') : null;
if (faviconEl) { if (faviconEl) {
faviconEl.setAttribute('href', originalFavicon); faviconEl.setAttribute('href', originalFavicon);
} }
}; };
window.gl.utils.resetFavicon = resetFavicon;
w.gl.utils.setCiStatusFavicon = (pageUrl) => { export const setCiStatusFavicon = (pageUrl) => {
$.ajax({ $.ajax({
url: pageUrl, url: pageUrl,
dataType: 'json', dataType: 'json',
success: function(data) { success: (data) => {
if (data && data.favicon) { if (data && data.favicon) {
gl.utils.setFavicon(data.favicon); gl.utils.setFavicon(data.favicon);
} else { } else {
gl.utils.resetFavicon(); gl.utils.resetFavicon();
} }
}, },
error: function() { error: () => {
gl.utils.resetFavicon(); gl.utils.resetFavicon();
} },
}); });
}; };
})(window); window.gl.utils.setCiStatusFavicon = setCiStatusFavicon;
}).call(window);
...@@ -7,6 +7,7 @@ import './flash'; ...@@ -7,6 +7,7 @@ import './flash';
import BlobForkSuggestion from './blob/blob_fork_suggestion'; import BlobForkSuggestion from './blob/blob_fork_suggestion';
import initChangesDropdown from './init_changes_dropdown'; import initChangesDropdown from './init_changes_dropdown';
import bp from './breakpoints'; import bp from './breakpoints';
import parseUrlPathname from './lib/utils/common_utils';
/* eslint-disable max-len */ /* eslint-disable max-len */
// MergeRequestTabs // MergeRequestTabs
...@@ -260,7 +261,7 @@ import bp from './breakpoints'; ...@@ -260,7 +261,7 @@ import bp from './breakpoints';
// We extract pathname for the current Changes tab anchor href // We extract pathname for the current Changes tab anchor href
// some pages like MergeRequestsController#new has query parameters on that anchor // some pages like MergeRequestsController#new has query parameters on that anchor
const urlPathname = gl.utils.parseUrlPathname(source); const urlPathname = parseUrlPathname(source);
this.ajaxGet({ this.ajaxGet({
url: `${urlPathname}.json${location.search}`, url: `${urlPathname}.json${location.search}`,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
import EmptyState from './empty_state.vue'; import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store'; import MonitoringStore from '../stores/monitoring_store';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import { backOff } from '../../lib/utils/common_utils';
export default { export default {
...@@ -41,7 +42,7 @@ ...@@ -41,7 +42,7 @@
getGraphsData() { getGraphsData() {
const maxNumberOfRequests = 3; const maxNumberOfRequests = 3;
this.state = 'loading'; this.state = 'loading';
gl.utils.backOff((next, stop) => { backOff((next, stop) => {
this.service.get().then((resp) => { this.service.get().then((resp) => {
if (resp.status === statusCodes.NO_CONTENT) { if (resp.status === statusCodes.NO_CONTENT) {
this.backOffRequestCounter = this.backOffRequestCounter += 1; this.backOffRequestCounter = this.backOffRequestCounter += 1;
......
...@@ -23,6 +23,7 @@ import loadAwardsHandler from './awards_handler'; ...@@ -23,6 +23,7 @@ import loadAwardsHandler from './awards_handler';
import './autosave'; import './autosave';
import './dropzone_input'; import './dropzone_input';
import TaskList from './task_list'; import TaskList from './task_list';
import { ajaxPost, isInViewport, getPagePath } from './lib/utils/common_utils';
window.autosize = autosize; window.autosize = autosize;
window.Dropzone = Dropzone; window.Dropzone = Dropzone;
...@@ -81,7 +82,7 @@ export default class Notes { ...@@ -81,7 +82,7 @@ export default class Notes {
this.setViewType(view); this.setViewType(view);
// We are in the Merge Requests page so we need another edit form for Changes tab // We are in the Merge Requests page so we need another edit form for Changes tab
if (gl.utils.getPagePath(1) === 'merge_requests') { if (getPagePath(1) === 'merge_requests') {
$('.note-edit-form').clone() $('.note-edit-form').clone()
.addClass('mr-note-edit-form').insertAfter('.note-edit-form'); .addClass('mr-note-edit-form').insertAfter('.note-edit-form');
} }
...@@ -644,10 +645,10 @@ export default class Notes { ...@@ -644,10 +645,10 @@ export default class Notes {
} }
else { else {
var $buttons = $el.find('.note-form-actions'); var $buttons = $el.find('.note-form-actions');
var isWidgetVisible = gl.utils.isInViewport($el.get(0)); var isWidgetVisible = isInViewport($el.get(0));
if (!isWidgetVisible) { if (!isWidgetVisible) {
gl.utils.scrollToElement($el); scrollToElement($el);
} }
$el.find('.js-finish-edit-warning').show(); $el.find('.js-finish-edit-warning').show();
...@@ -1188,7 +1189,7 @@ export default class Notes { ...@@ -1188,7 +1189,7 @@ export default class Notes {
} }
static checkMergeRequestStatus() { static checkMergeRequestStatus() {
if (gl.utils.getPagePath(1) === 'merge_requests') { if (getPagePath(1) === 'merge_requests') {
gl.mrWidget.checkStatus(); gl.mrWidget.checkStatus();
} }
} }
...@@ -1326,7 +1327,7 @@ export default class Notes { ...@@ -1326,7 +1327,7 @@ export default class Notes {
* 2) Identify comment type; a) Main thread b) Discussion thread c) Discussion resolve * 2) Identify comment type; a) Main thread b) Discussion thread c) Discussion resolve
* 3) Build temporary placeholder element (using `createPlaceholderNote`) * 3) Build temporary placeholder element (using `createPlaceholderNote`)
* 4) Show placeholder note on UI * 4) Show placeholder note on UI
* 5) Perform network request to submit the note using `gl.utils.ajaxPost` * 5) Perform network request to submit the note using `ajaxPost`
* a) If request is successfully completed * a) If request is successfully completed
* 1. Remove placeholder element * 1. Remove placeholder element
* 2. Show submitted Note element * 2. Show submitted Note element
...@@ -1408,7 +1409,7 @@ export default class Notes { ...@@ -1408,7 +1409,7 @@ export default class Notes {
/* eslint-disable promise/catch-or-return */ /* eslint-disable promise/catch-or-return */
// Make request to submit comment on server // Make request to submit comment on server
gl.utils.ajaxPost(formAction, formData) ajaxPost(formAction, formData)
.then((note) => { .then((note) => {
// Submission successful! remove placeholder // Submission successful! remove placeholder
$notesContainer.find(`#${noteUniqueId}`).remove(); $notesContainer.find(`#${noteUniqueId}`).remove();
...@@ -1510,7 +1511,7 @@ export default class Notes { ...@@ -1510,7 +1511,7 @@ export default class Notes {
/* eslint-disable promise/catch-or-return */ /* eslint-disable promise/catch-or-return */
// Make request to update comment on server // Make request to update comment on server
gl.utils.ajaxPost(formAction, formData) ajaxPost(formAction, formData)
.then((note) => { .then((note) => {
// Submission successful! render final note element // Submission successful! render final note element
this.updateNote(note, $editingNote); this.updateNote(note, $editingNote);
......
...@@ -7,6 +7,7 @@ import * as constants from '../constants'; ...@@ -7,6 +7,7 @@ import * as constants from '../constants';
import service from '../services/issue_notes_service'; import service from '../services/issue_notes_service';
import loadAwardsHandler from '../../awards_handler'; import loadAwardsHandler from '../../awards_handler';
import sidebarTimeTrackingEventHub from '../../sidebar/event_hub'; import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
import { isInViewport, scrollToElement } from '../../lib/utils/common_utils';
let eTagPoll; let eTagPoll;
...@@ -211,7 +212,7 @@ export const toggleAwardRequest = ({ commit, getters, dispatch }, data) => { ...@@ -211,7 +212,7 @@ export const toggleAwardRequest = ({ commit, getters, dispatch }, data) => {
}; };
export const scrollToNoteIfNeeded = (context, el) => { export const scrollToNoteIfNeeded = (context, el) => {
if (!gl.utils.isInViewport(el[0])) { if (!isInViewport(el[0])) {
gl.utils.scrollToElement(el); scrollToElement(el);
} }
}; };
/* eslint-disable comma-dangle, no-unused-vars, class-methods-use-this, quotes, consistent-return, func-names, prefer-arrow-callback, space-before-function-paren, max-len */ /* eslint-disable comma-dangle, no-unused-vars, class-methods-use-this, quotes, consistent-return, func-names, prefer-arrow-callback, space-before-function-paren, max-len */
/* global Flash */ /* global Flash */
import { getPagePath } from '../lib/utils/common_utils';
((global) => { ((global) => {
class Profile { class Profile {
...@@ -93,7 +94,7 @@ ...@@ -93,7 +94,7 @@
return $title.val(comment[1]).change(); return $title.val(comment[1]).change();
} }
}); });
if (global.utils.getPagePath() === 'profiles') { if (getPagePath() === 'profiles') {
return new Profile(); return new Profile();
} }
}); });
......
import PANEL_STATE from './constants'; import PANEL_STATE from './constants';
import { backOff } from '../lib/utils/common_utils';
export default class PrometheusMetrics { export default class PrometheusMetrics {
constructor(wrapperSelector) { constructor(wrapperSelector) {
...@@ -79,7 +80,7 @@ export default class PrometheusMetrics { ...@@ -79,7 +80,7 @@ export default class PrometheusMetrics {
loadActiveMetrics() { loadActiveMetrics() {
this.showMonitoringMetricsPanelState(PANEL_STATE.LOADING); this.showMonitoringMetricsPanelState(PANEL_STATE.LOADING);
gl.utils.backOff((next, stop) => { backOff((next, stop) => {
$.getJSON(this.activeMetricsEndpoint) $.getJSON(this.activeMetricsEndpoint)
.done((res) => { .done((res) => {
if (res && res.success) { if (res && res.success) {
......
/* eslint-disable comma-dangle, no-return-assign, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-unused-vars, no-cond-assign, consistent-return, object-shorthand, prefer-arrow-callback, func-names, space-before-function-paren, prefer-template, quotes, class-methods-use-this, no-unused-expressions, no-sequences, wrap-iife, no-lonely-if, no-else-return, no-param-reassign, vars-on-top, max-len */ /* eslint-disable comma-dangle, no-return-assign, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-unused-vars, no-cond-assign, consistent-return, object-shorthand, prefer-arrow-callback, func-names, space-before-function-paren, prefer-template, quotes, class-methods-use-this, no-unused-expressions, no-sequences, wrap-iife, no-lonely-if, no-else-return, no-param-reassign, vars-on-top, max-len */
import { isInGroupsPage, isInProjectPage, getGroupSlug, getProjectSlug } from './lib/utils/common_utils';
((global) => { ((global) => {
const KEYCODE = { const KEYCODE = {
...@@ -146,14 +147,14 @@ ...@@ -146,14 +147,14 @@
} }
getCategoryContents() { getCategoryContents() {
var dashboardOptions, groupOptions, issuesPath, items, mrPath, name, options, projectOptions, userId, userName, utils; var dashboardOptions, groupOptions, issuesPath, items, mrPath, name, options, projectOptions, userId, userName;
userId = gon.current_user_id; userId = gon.current_user_id;
userName = gon.current_username; userName = gon.current_username;
utils = gl.utils, projectOptions = gl.projectOptions, groupOptions = gl.groupOptions, dashboardOptions = gl.dashboardOptions; projectOptions = gl.projectOptions, groupOptions = gl.groupOptions, dashboardOptions = gl.dashboardOptions;
if (utils.isInGroupsPage() && groupOptions) { if (isInGroupsPage() && groupOptions) {
options = groupOptions[utils.getGroupSlug()]; options = groupOptions[getGroupSlug()];
} else if (utils.isInProjectPage() && projectOptions) { } else if (isInProjectPage() && projectOptions) {
options = projectOptions[utils.getProjectSlug()]; options = projectOptions[getProjectSlug()];
} else if (dashboardOptions) { } else if (dashboardOptions) {
options = dashboardOptions; options = dashboardOptions;
} }
......
import statusCodes from '../../lib/utils/http_status'; import statusCodes from '../../lib/utils/http_status';
import { bytesToMiB } from '../../lib/utils/number_utils'; import { bytesToMiB } from '../../lib/utils/number_utils';
import { backOff } from '../../lib/utils/common_utils';
import MemoryGraph from '../../vue_shared/components/memory_graph'; import MemoryGraph from '../../vue_shared/components/memory_graph';
import MRWidgetService from '../services/mr_widget_service'; import MRWidgetService from '../services/mr_widget_service';
...@@ -84,7 +84,7 @@ export default { ...@@ -84,7 +84,7 @@ export default {
} }
}, },
loadMetrics() { loadMetrics() {
gl.utils.backOff((next, stop) => { backOff((next, stop) => {
MRWidgetService.fetchMetrics(this.metricsUrl) MRWidgetService.fetchMetrics(this.metricsUrl)
.then((res) => { .then((res) => {
if (res.status === statusCodes.NO_CONTENT) { if (res.status === statusCodes.NO_CONTENT) {
......
/* eslint-disable promise/catch-or-return */ /* eslint-disable promise/catch-or-return */
import '~/lib/utils/common_utils'; import * as commonUtils from '~/lib/utils/common_utils';
(() => { describe('common_utils', () => {
describe('common_utils', () => { describe('parseUrl', () => {
describe('gl.utils.parseUrl', () => {
it('returns an anchor tag with url', () => { it('returns an anchor tag with url', () => {
expect(gl.utils.parseUrl('/some/absolute/url').pathname).toContain('some/absolute/url'); expect(commonUtils.parseUrl('/some/absolute/url').pathname).toContain('some/absolute/url');
}); });
it('url is escaped', () => { it('url is escaped', () => {
// IE11 will return a relative pathname while other browsers will return a full pathname. // IE11 will return a relative pathname while other browsers will return a full pathname.
...@@ -14,21 +13,21 @@ import '~/lib/utils/common_utils'; ...@@ -14,21 +13,21 @@ import '~/lib/utils/common_utils';
// element will create an absolute url relative to the current execution context. // element will create an absolute url relative to the current execution context.
// The JavaScript test suite is executed at '/' which will lead to an absolute url // The JavaScript test suite is executed at '/' which will lead to an absolute url
// starting with '/'. // starting with '/'.
expect(gl.utils.parseUrl('" test="asf"').pathname).toContain('/%22%20test=%22asf%22'); expect(commonUtils.parseUrl('" test="asf"').pathname).toContain('/%22%20test=%22asf%22');
}); });
}); });
describe('gl.utils.parseUrlPathname', () => { describe('parseUrlPathname', () => {
beforeEach(() => { beforeEach(() => {
spyOn(gl.utils, 'parseUrl').and.callFake(url => ({ spyOn(gl.utils, 'parseUrl').and.callFake(url => ({
pathname: url, pathname: url,
})); }));
}); });
it('returns an absolute url when given an absolute url', () => { it('returns an absolute url when given an absolute url', () => {
expect(gl.utils.parseUrlPathname('/some/absolute/url')).toEqual('/some/absolute/url'); expect(commonUtils.parseUrlPathname('/some/absolute/url')).toEqual('/some/absolute/url');
}); });
it('returns an absolute url when given a relative url', () => { it('returns an absolute url when given a relative url', () => {
expect(gl.utils.parseUrlPathname('some/relative/url')).toEqual('/some/relative/url'); expect(commonUtils.parseUrlPathname('some/relative/url')).toEqual('/some/relative/url');
}); });
}); });
...@@ -53,7 +52,7 @@ import '~/lib/utils/common_utils'; ...@@ -53,7 +52,7 @@ import '~/lib/utils/common_utils';
}); });
}); });
describe('gl.utils.handleLocationHash', () => { describe('handleLocationHash', () => {
beforeEach(() => { beforeEach(() => {
spyOn(window.document, 'getElementById').and.callThrough(); spyOn(window.document, 'getElementById').and.callThrough();
}); });
...@@ -68,7 +67,7 @@ import '~/lib/utils/common_utils'; ...@@ -68,7 +67,7 @@ import '~/lib/utils/common_utils';
it('decodes hash parameter', () => { it('decodes hash parameter', () => {
window.history.pushState({}, null, '#random-hash'); window.history.pushState({}, null, '#random-hash');
gl.utils.handleLocationHash(); commonUtils.handleLocationHash();
expectGetElementIdToHaveBeenCalledWith('random-hash'); expectGetElementIdToHaveBeenCalledWith('random-hash');
expectGetElementIdToHaveBeenCalledWith('user-content-random-hash'); expectGetElementIdToHaveBeenCalledWith('user-content-random-hash');
...@@ -76,7 +75,7 @@ import '~/lib/utils/common_utils'; ...@@ -76,7 +75,7 @@ import '~/lib/utils/common_utils';
it('decodes cyrillic hash parameter', () => { it('decodes cyrillic hash parameter', () => {
window.history.pushState({}, null, '#definição'); window.history.pushState({}, null, '#definição');
gl.utils.handleLocationHash(); commonUtils.handleLocationHash();
expectGetElementIdToHaveBeenCalledWith('definição'); expectGetElementIdToHaveBeenCalledWith('definição');
expectGetElementIdToHaveBeenCalledWith('user-content-definição'); expectGetElementIdToHaveBeenCalledWith('user-content-definição');
...@@ -84,7 +83,7 @@ import '~/lib/utils/common_utils'; ...@@ -84,7 +83,7 @@ import '~/lib/utils/common_utils';
it('decodes encoded cyrillic hash parameter', () => { it('decodes encoded cyrillic hash parameter', () => {
window.history.pushState({}, null, '#defini%C3%A7%C3%A3o'); window.history.pushState({}, null, '#defini%C3%A7%C3%A3o');
gl.utils.handleLocationHash(); commonUtils.handleLocationHash();
expectGetElementIdToHaveBeenCalledWith('definição'); expectGetElementIdToHaveBeenCalledWith('definição');
expectGetElementIdToHaveBeenCalledWith('user-content-definição'); expectGetElementIdToHaveBeenCalledWith('user-content-definição');
...@@ -265,7 +264,7 @@ import '~/lib/utils/common_utils'; ...@@ -265,7 +264,7 @@ import '~/lib/utils/common_utils';
}); });
}); });
describe('gl.utils.backOff', () => { describe('backOff', () => {
beforeEach(() => { beforeEach(() => {
// shortcut our timeouts otherwise these tests will take a long time to finish // shortcut our timeouts otherwise these tests will take a long time to finish
const origSetTimeout = window.setTimeout; const origSetTimeout = window.setTimeout;
...@@ -274,7 +273,7 @@ import '~/lib/utils/common_utils'; ...@@ -274,7 +273,7 @@ import '~/lib/utils/common_utils';
it('solves the promise from the callback', (done) => { it('solves the promise from the callback', (done) => {
const expectedResponseValue = 'Success!'; const expectedResponseValue = 'Success!';
gl.utils.backOff((next, stop) => ( commonUtils.backOff((next, stop) => (
new Promise((resolve) => { new Promise((resolve) => {
resolve(expectedResponseValue); resolve(expectedResponseValue);
}).then((resp) => { }).then((resp) => {
...@@ -288,7 +287,7 @@ import '~/lib/utils/common_utils'; ...@@ -288,7 +287,7 @@ import '~/lib/utils/common_utils';
it('catches the rejected promise from the callback ', (done) => { it('catches the rejected promise from the callback ', (done) => {
const errorMessage = 'Mistakes were made!'; const errorMessage = 'Mistakes were made!';
gl.utils.backOff((next, stop) => { commonUtils.backOff((next, stop) => {
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
reject(new Error(errorMessage)); reject(new Error(errorMessage));
}).then((resp) => { }).then((resp) => {
...@@ -304,7 +303,7 @@ import '~/lib/utils/common_utils'; ...@@ -304,7 +303,7 @@ import '~/lib/utils/common_utils';
it('solves the promise correctly after retrying a third time', (done) => { it('solves the promise correctly after retrying a third time', (done) => {
let numberOfCalls = 1; let numberOfCalls = 1;
const expectedResponseValue = 'Success!'; const expectedResponseValue = 'Success!';
gl.utils.backOff((next, stop) => ( commonUtils.backOff((next, stop) => (
Promise.resolve(expectedResponseValue) Promise.resolve(expectedResponseValue)
.then((resp) => { .then((resp) => {
if (numberOfCalls < 3) { if (numberOfCalls < 3) {
...@@ -323,7 +322,7 @@ import '~/lib/utils/common_utils'; ...@@ -323,7 +322,7 @@ import '~/lib/utils/common_utils';
}); });
it('rejects the backOff promise after timing out', (done) => { it('rejects the backOff promise after timing out', (done) => {
gl.utils.backOff(next => next(), 64000) commonUtils.backOff(next => next(), 64000)
.catch((errBackoffResp) => { .catch((errBackoffResp) => {
const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout); const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]); expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
...@@ -384,15 +383,14 @@ import '~/lib/utils/common_utils'; ...@@ -384,15 +383,14 @@ import '~/lib/utils/common_utils';
}); });
}); });
describe('gl.utils.ajaxPost', () => { describe('ajaxPost', () => {
it('should perform `$.ajax` call and do `POST` request', () => { it('should perform `$.ajax` call and do `POST` request', () => {
const requestURL = '/some/random/api'; const requestURL = '/some/random/api';
const data = { keyname: 'value' }; const data = { keyname: 'value' };
const ajaxSpy = spyOn($, 'ajax').and.callFake(() => {}); const ajaxSpy = spyOn($, 'ajax').and.callFake(() => {});
gl.utils.ajaxPost(requestURL, data); commonUtils.ajaxPost(requestURL, data);
expect(ajaxSpy.calls.allArgs()[0][0].type).toEqual('POST'); expect(ajaxSpy.calls.allArgs()[0][0].type).toEqual('POST');
}); });
}); });
}); });
})();
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment