diff --git a/app/assets/javascripts/abuse_reports.js b/app/assets/javascripts/abuse_reports.js index 3de192d56eb..d2d3a257c0d 100644 --- a/app/assets/javascripts/abuse_reports.js +++ b/app/assets/javascripts/abuse_reports.js @@ -1,3 +1,5 @@ +import { truncate } from './lib/utils/text_utility'; + const MAX_MESSAGE_LENGTH = 500; const MESSAGE_CELL_SELECTOR = '.abuse-reports .message'; @@ -15,7 +17,7 @@ export default class AbuseReports { if (reportMessage.length > MAX_MESSAGE_LENGTH) { $messageCellElement.data('original-message', reportMessage); $messageCellElement.data('message-truncated', 'true'); - $messageCellElement.text(window.gl.text.truncate(reportMessage, MAX_MESSAGE_LENGTH)); + $messageCellElement.text(truncate(reportMessage, MAX_MESSAGE_LENGTH)); } } diff --git a/app/assets/javascripts/boards/components/modal/footer.js b/app/assets/javascripts/boards/components/modal/footer.js index de9e44cef35..182957113a2 100644 --- a/app/assets/javascripts/boards/components/modal/footer.js +++ b/app/assets/javascripts/boards/components/modal/footer.js @@ -3,6 +3,7 @@ import Vue from 'vue'; import Flash from '../../../flash'; import './lists_dropdown'; +import { pluralize } from '../../../lib/utils/text_utility'; const ModalStore = gl.issueBoards.ModalStore; @@ -21,7 +22,7 @@ gl.issueBoards.ModalFooter = Vue.extend({ submitText() { const count = ModalStore.selectedCount(); - return `Add ${count > 0 ? count : ''} ${gl.text.pluralize('issue', count)}`; + return `Add ${count > 0 ? count : ''} ${pluralize('issue', count)}`; }, }, methods: { diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js index ae6b8902032..9b952ea7b60 100644 --- a/app/assets/javascripts/commits.js +++ b/app/assets/javascripts/commits.js @@ -3,6 +3,8 @@ prefer-template, object-shorthand, prefer-arrow-callback */ /* global Pager */ +import { pluralize } from './lib/utils/text_utility'; + export default (function () { const CommitsList = {}; @@ -86,7 +88,7 @@ export default (function () { // Update commits count in the previous commits header. commitsCount += Number($(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length); - $commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${gl.text.pluralize('commit', commitsCount)}`); + $commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${pluralize('commit', commitsCount)}`); } gl.utils.localTimeAgo($processedData.find('.js-timeago')); diff --git a/app/assets/javascripts/create_label.js b/app/assets/javascripts/create_label.js index 3bed0678350..9a4c9bfcc80 100644 --- a/app/assets/javascripts/create_label.js +++ b/app/assets/javascripts/create_label.js @@ -1,5 +1,6 @@ /* eslint-disable func-names, prefer-arrow-callback */ import Api from './api'; +import { humanize } from './lib/utils/text_utility'; export default class CreateLabelDropdown { constructor($el, namespacePath, projectPath) { @@ -107,7 +108,7 @@ export default class CreateLabelDropdown { errors = label.message; } else { errors = Object.keys(label.message).map(key => - `${gl.text.humanize(key)} ${label.message[key].join(', ')}`, + `${humanize(key)} ${label.message[key].join(', ')}`, ).join('
'); } diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js index 8bf9ae17de0..a8cd8c20f8f 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js @@ -1,7 +1,7 @@ /* eslint-disable no-param-reassign */ import { __ } from '../locale'; -import '../lib/utils/text_utility'; +import { dasherize } from '../lib/utils/text_utility'; import DEFAULT_EVENT_OBJECTS from './default_event_objects'; const EMPTY_STAGE_TEXTS = { @@ -36,7 +36,7 @@ export default { }); newData.stages.forEach((item) => { - const stageSlug = gl.text.dasherize(item.name.toLowerCase()); + const stageSlug = dasherize(item.name.toLowerCase()); item.active = false; item.isUserAllowed = data.permissions[stageSlug]; item.emptyStageText = EMPTY_STAGE_TEXTS[stageSlug]; diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index fc0308b81ba..9d25f806c0d 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -2,7 +2,7 @@ import Timeago from 'timeago.js'; import _ from 'underscore'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; -import '../../lib/utils/text_utility'; +import { humanize } from '../../lib/utils/text_utility'; import ActionsComponent from './environment_actions.vue'; import ExternalUrlComponent from './environment_external_url.vue'; import StopComponent from './environment_stop.vue'; @@ -139,7 +139,7 @@ export default { if (this.hasManualActions) { return this.model.last_deployment.manual_actions.map((action) => { const parsedAction = { - name: gl.text.humanize(action.name), + name: humanize(action.name), play_path: action.play_path, playable: action.playable, }; diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js index 48cd43d3348..d0f9e6af0f8 100644 --- a/app/assets/javascripts/gl_form.js +++ b/app/assets/javascripts/gl_form.js @@ -2,6 +2,7 @@ import GfmAutoComplete from './gfm_auto_complete'; import dropzoneInput from './dropzone_input'; +import textUtils from './lib/utils/text_markdown'; export default class GLForm { constructor(form, enableGFM = false) { @@ -46,7 +47,7 @@ export default class GLForm { } // form and textarea event listeners this.addEventListeners(); - gl.text.init(this.form); + textUtils.init(this.form); // hide discard button this.form.find('.js-note-discard').hide(); this.form.show(); @@ -85,7 +86,7 @@ export default class GLForm { clearEventListeners() { this.textarea.off('focus'); this.textarea.off('blur'); - gl.text.removeListeners(this.form); + textUtils.removeListeners(this.form); } addEventListeners() { diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index acd5730cf3c..7de07e9403d 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -1,6 +1,6 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, max-len */ import 'vendor/jquery.waitforimages'; -import '~/lib/utils/text_utility'; +import { addDelimiter } from './lib/utils/text_utility'; import Flash from './flash'; import TaskList from './task_list'; import CreateMergeRequestDropdown from './create_merge_request_dropdown'; @@ -73,7 +73,7 @@ export default class Issue { let numProjectIssues = Number(projectIssuesCounter.first().text().trim().replace(/[^\d]/, '')); numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1; - projectIssuesCounter.text(gl.text.addDelimiter(numProjectIssues)); + projectIssuesCounter.text(addDelimiter(numProjectIssues)); if (this.createMergeRequestDropdown) { if (isClosed) { diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 07899777a1e..5c4926d6ac8 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -172,7 +172,6 @@ export const getSelectedFragment = () => { return documentFragment; }; -// TODO: Update this name, there is a gl.text.insertText function. export const insertText = (target, text) => { // Firefox doesn't support `document.execCommand('insertText', false, text)` on textareas const selectionStart = target.selectionStart; diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 29fc91733b3..5679b8c9a09 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -2,6 +2,7 @@ import timeago from 'timeago.js'; import dateFormat from 'vendor/date.format'; +import { pluralize } from './text_utility'; import { lang, @@ -143,9 +144,9 @@ export function timeIntervalInWords(intervalInSeconds) { let text = ''; if (minutes >= 1) { - text = `${minutes} ${gl.text.pluralize('minute', minutes)} ${seconds} ${gl.text.pluralize('second', seconds)}`; + text = `${minutes} ${pluralize('minute', minutes)} ${seconds} ${pluralize('second', seconds)}`; } else { - text = `${seconds} ${gl.text.pluralize('second', seconds)}`; + text = `${seconds} ${pluralize('second', seconds)}`; } return text; } diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js new file mode 100644 index 00000000000..2dc9cf0cc29 --- /dev/null +++ b/app/assets/javascripts/lib/utils/text_markdown.js @@ -0,0 +1,153 @@ +/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */ + +const textUtils = {}; + +textUtils.selectedText = function(text, textarea) { + return text.substring(textarea.selectionStart, textarea.selectionEnd); +}; + +textUtils.lineBefore = function(text, textarea) { + var split; + split = text.substring(0, textarea.selectionStart).trim().split('\n'); + return split[split.length - 1]; +}; + +textUtils.lineAfter = function(text, textarea) { + return text.substring(textarea.selectionEnd).trim().split('\n')[0]; +}; + +textUtils.blockTagText = function(text, textArea, blockTag, selected) { + var lineAfter, lineBefore; + lineBefore = this.lineBefore(text, textArea); + lineAfter = this.lineAfter(text, textArea); + if (lineBefore === blockTag && lineAfter === blockTag) { + // To remove the block tag we have to select the line before & after + if (blockTag != null) { + textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1); + textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1); + } + return selected; + } else { + return blockTag + "\n" + selected + "\n" + blockTag; + } +}; + +textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) { + var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine; + removedLastNewLine = false; + removedFirstNewLine = false; + currentLineEmpty = false; + + // Remove the first newline + if (selected.indexOf('\n') === 0) { + removedFirstNewLine = true; + selected = selected.replace(/\n+/, ''); + } + + // Remove the last newline + if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) { + removedLastNewLine = true; + selected = selected.replace(/\n$/, ''); + } + + selectedSplit = selected.split('\n'); + + if (!wrap) { + lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n'); + + // Check whether the current line is empty or consists only of spaces(=handle as empty) + if (/^\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) { + currentLineEmpty = true; + } + } + + startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : ''; + + if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) { + if (blockTag != null && blockTag !== '') { + insertText = this.blockTagText(text, textArea, blockTag, selected); + } else { + insertText = selectedSplit.map(function(val) { + if (val.indexOf(tag) === 0) { + return "" + (val.replace(tag, '')); + } else { + return "" + tag + val; + } + }).join('\n'); + } + } else { + insertText = "" + startChar + tag + selected + (wrap ? tag : ' '); + } + + if (removedFirstNewLine) { + insertText = '\n' + insertText; + } + + if (removedLastNewLine) { + insertText += '\n'; + } + + if (document.queryCommandSupported('insertText')) { + inserted = document.execCommand('insertText', false, insertText); + } + if (!inserted) { + try { + document.execCommand("ms-beginUndoUnit"); + } catch (error) {} + textArea.value = this.replaceRange(text, textArea.selectionStart, textArea.selectionEnd, insertText); + try { + document.execCommand("ms-endUndoUnit"); + } catch (error) {} + } + return this.moveCursor(textArea, tag, wrap, removedLastNewLine); +}; + +textUtils.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) { + var pos; + if (!textArea.setSelectionRange) { + return; + } + if (textArea.selectionStart === textArea.selectionEnd) { + if (wrapped) { + pos = textArea.selectionStart - tag.length; + } else { + pos = textArea.selectionStart; + } + + if (removedLastNewLine) { + pos -= 1; + } + + return textArea.setSelectionRange(pos, pos); + } +}; + +textUtils.updateText = function(textArea, tag, blockTag, wrap) { + var $textArea, selected, text; + $textArea = $(textArea); + textArea = $textArea.get(0); + text = $textArea.val(); + selected = this.selectedText(text, textArea); + $textArea.focus(); + return this.insertText(textArea, text, tag, blockTag, selected, wrap); +}; + +textUtils.init = function(form) { + var self; + self = this; + return $('.js-md', form).off('click').on('click', function() { + var $this; + $this = $(this); + return self.updateText($this.closest('.md-area').find('textarea'), $this.data('md-tag'), $this.data('md-block'), !$this.data('md-prepend')); + }); +}; + +textUtils.removeListeners = function(form) { + return $('.js-md', form).off('click'); +}; + +textUtils.replaceRange = function(s, start, end, substitute) { + return s.substring(0, start) + substitute + s.substring(end); +}; + +export default textUtils; diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index f776829f69c..28ab9dddc4c 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -1,18 +1,13 @@ -/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */ - -import 'vendor/latinise'; - -var base; -var w = window; -if (w.gl == null) { - w.gl = {}; -} -if ((base = w.gl).text == null) { - base.text = {}; -} -gl.text.addDelimiter = function(text) { - return text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : text; -}; +/** + * Adds a , to a string composed by numbers, at every 3 chars. + * + * 2333 -> 2,333 + * 232324 -> 232,324 + * + * @param {String} text + * @returns {String} + */ +export const addDelimiter = text => (text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text); /** * Returns '99+' for numbers bigger than 99. @@ -20,178 +15,43 @@ gl.text.addDelimiter = function(text) { * @param {Number} count * @return {Number|String} */ -export function highCountTrim(count) { - return count > 99 ? '99+' : count; -} +export const highCountTrim = count => (count > 99 ? '99+' : count); -gl.text.randomString = function() { - return Math.random().toString(36).substring(7); -}; -gl.text.replaceRange = function(s, start, end, substitute) { - return s.substring(0, start) + substitute + s.substring(end); -}; -gl.text.getTextWidth = function(text, font) { - /** - * Uses canvas.measureText to compute and return the width of the given text of given font in pixels. - * - * @param {String} text The text to be rendered. - * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana"). - * - * @see http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393 - */ - // re-use canvas object for better performance - var canvas = gl.text.getTextWidth.canvas || (gl.text.getTextWidth.canvas = document.createElement('canvas')); - var context = canvas.getContext('2d'); - context.font = font; - return context.measureText(text).width; -}; -gl.text.selectedText = function(text, textarea) { - return text.substring(textarea.selectionStart, textarea.selectionEnd); -}; -gl.text.lineBefore = function(text, textarea) { - var split; - split = text.substring(0, textarea.selectionStart).trim().split('\n'); - return split[split.length - 1]; -}; -gl.text.lineAfter = function(text, textarea) { - return text.substring(textarea.selectionEnd).trim().split('\n')[0]; -}; -gl.text.blockTagText = function(text, textArea, blockTag, selected) { - var lineAfter, lineBefore; - lineBefore = this.lineBefore(text, textArea); - lineAfter = this.lineAfter(text, textArea); - if (lineBefore === blockTag && lineAfter === blockTag) { - // To remove the block tag we have to select the line before & after - if (blockTag != null) { - textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1); - textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1); - } - return selected; - } else { - return blockTag + "\n" + selected + "\n" + blockTag; - } -}; -gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) { - var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine; - removedLastNewLine = false; - removedFirstNewLine = false; - currentLineEmpty = false; +/** + * Converst first char to uppercase and replaces undercores with spaces + * @param {String} string + * @requires {String} + */ +export const humanize = string => string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1); - // Remove the first newline - if (selected.indexOf('\n') === 0) { - removedFirstNewLine = true; - selected = selected.replace(/\n+/, ''); - } +/** + * Adds an 's' to the end of the string when count is bigger than 0 + * @param {String} str + * @param {Number} count + * @returns {String} + */ +export const pluralize = (str, count) => str + (count > 1 || count === 0 ? 's' : ''); - // Remove the last newline - if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) { - removedLastNewLine = true; - selected = selected.replace(/\n$/, ''); - } +/** + * Replaces underscores with dashes + * @param {*} str + * @returns {String} + */ +export const dasherize = str => str.replace(/[_\s]+/g, '-'); - selectedSplit = selected.split('\n'); +/** + * Removes accents and converts to lower case + * @param {String} str + * @returns {String} + */ +export const slugify = str => str.trim().toLowerCase(); - if (!wrap) { - lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n'); +/** + * Truncates given text + * + * @param {String} string + * @param {Number} maxLength + * @returns {String} + */ +export const truncate = (string, maxLength) => `${string.substr(0, (maxLength - 3))}...`; - // Check whether the current line is empty or consists only of spaces(=handle as empty) - if (/^\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) { - currentLineEmpty = true; - } - } - - startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : ''; - - if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) { - if (blockTag != null && blockTag !== '') { - insertText = this.blockTagText(text, textArea, blockTag, selected); - } else { - insertText = selectedSplit.map(function(val) { - if (val.indexOf(tag) === 0) { - return "" + (val.replace(tag, '')); - } else { - return "" + tag + val; - } - }).join('\n'); - } - } else { - insertText = "" + startChar + tag + selected + (wrap ? tag : ' '); - } - - if (removedFirstNewLine) { - insertText = '\n' + insertText; - } - - if (removedLastNewLine) { - insertText += '\n'; - } - - if (document.queryCommandSupported('insertText')) { - inserted = document.execCommand('insertText', false, insertText); - } - if (!inserted) { - try { - document.execCommand("ms-beginUndoUnit"); - } catch (error) {} - textArea.value = this.replaceRange(text, textArea.selectionStart, textArea.selectionEnd, insertText); - try { - document.execCommand("ms-endUndoUnit"); - } catch (error) {} - } - return this.moveCursor(textArea, tag, wrap, removedLastNewLine); -}; -gl.text.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) { - var pos; - if (!textArea.setSelectionRange) { - return; - } - if (textArea.selectionStart === textArea.selectionEnd) { - if (wrapped) { - pos = textArea.selectionStart - tag.length; - } else { - pos = textArea.selectionStart; - } - - if (removedLastNewLine) { - pos -= 1; - } - - return textArea.setSelectionRange(pos, pos); - } -}; -gl.text.updateText = function(textArea, tag, blockTag, wrap) { - var $textArea, selected, text; - $textArea = $(textArea); - textArea = $textArea.get(0); - text = $textArea.val(); - selected = this.selectedText(text, textArea); - $textArea.focus(); - return this.insertText(textArea, text, tag, blockTag, selected, wrap); -}; -gl.text.init = function(form) { - var self; - self = this; - return $('.js-md', form).off('click').on('click', function() { - var $this; - $this = $(this); - return self.updateText($this.closest('.md-area').find('textarea'), $this.data('md-tag'), $this.data('md-block'), !$this.data('md-prepend')); - }); -}; -gl.text.removeListeners = function(form) { - return $('.js-md', form).off('click'); -}; -gl.text.humanize = function(string) { - return string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1); -}; -gl.text.pluralize = function(str, count) { - return str + (count > 1 || count === 0 ? 's' : ''); -}; -gl.text.truncate = function(string, maxLength) { - return string.substr(0, (maxLength - 3)) + '...'; -}; -gl.text.dasherize = function(str) { - return str.replace(/[_\s]+/g, '-'); -}; -gl.text.slugify = function(str) { - return str.trim().toLowerCase().latinise(); -}; diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 31c5cfc5e55..127fddcf8d3 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -30,7 +30,6 @@ import './commit/image_file'; import { handleLocationHash } from './lib/utils/common_utils'; import './lib/utils/datetime_utility'; import './lib/utils/pretty_time'; -import './lib/utils/text_utility'; import './lib/utils/url_utility'; // behaviors diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index af0658eb668..d30ff12bb59 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -5,6 +5,7 @@ import 'vendor/jquery.waitforimages'; import TaskList from './task_list'; import './merge_request_tabs'; import IssuablesHelper from './helpers/issuables_helper'; +import { addDelimiter } from './lib/utils/text_utility'; (function() { this.MergeRequest = (function() { @@ -124,7 +125,7 @@ import IssuablesHelper from './helpers/issuables_helper'; const $el = $('.nav-links .js-merge-counter'); const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0); - $el.text(gl.text.addDelimiter(count)); + $el.text(addDelimiter(count)); }; MergeRequest.prototype.hideCloseButton = function() { diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue index 547140b1a43..19d8e1f49cf 100644 --- a/app/assets/javascripts/pipelines/components/graph/action_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue @@ -1,7 +1,7 @@