Commit 53e11239 authored by Mike Greiling's avatar Mike Greiling

Merge branch 'master' into sh-headless-chrome-support

* master: (104 commits)
  Update licenses
  fix a wrong method call in the refactor
  fix a whitespace
  fix for discussion
  Update templates via:
  Update doc accordingly to:
  Cache issuable template names
  Fix the format of rugged alternate directory list
  Match full file path in FileDetector
  Fixes from CSS refactor
  Resolve "Prometheus service page shows error"
  Explicit state integration deletion
  Move all API authentication code to APIGuard
  Shorten example translation for inclusive language
  [ci-skip] add changelog
  fix the merger override to remove source branch
  add spec
  Removed d3.js  from the users and graphs bundle
  Cleanup data-page attribute after each Karma test
  Update template description wording
  ...
parents d8cc4540 8d47e9f8
...@@ -296,9 +296,9 @@ might be edited to make them small and simple. ...@@ -296,9 +296,9 @@ might be edited to make them small and simple.
Please submit Feature Proposals using the ['Feature Proposal' issue template](.gitlab/issue_templates/Feature Proposal.md) provided on the issue tracker. Please submit Feature Proposals using the ['Feature Proposal' issue template](.gitlab/issue_templates/Feature Proposal.md) provided on the issue tracker.
For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should
be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may
need to ask one of the [core team] members to add the label, if you do not have permissions to do it by yourself. need to ask one of the [core team] members to add the label, if you do not have permissions to do it by yourself.
If you want to create something yourself, consider opening an issue first to If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab. discuss whether it is interesting to include this in GitLab.
...@@ -658,7 +658,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor ...@@ -658,7 +658,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[license-finder-doc]: doc/development/licensing.md [license-finder-doc]: doc/development/licensing.md
[GitLab Inc engineering workflow]: https://about.gitlab.com/handbook/engineering/workflow/#labelling-issues [GitLab Inc engineering workflow]: https://about.gitlab.com/handbook/engineering/workflow/#labelling-issues
[polling-etag]: https://docs.gitlab.com/ce/development/polling.html [polling-etag]: https://docs.gitlab.com/ce/development/polling.html
[testing]: doc/development/testing.md [testing]: doc/development/testing_guide/index.md
[^1]: Please note that specs other than JavaScript specs are considered backend [^1]: Please note that specs other than JavaScript specs are considered backend
code. code.
...@@ -398,7 +398,7 @@ group :ed25519 do ...@@ -398,7 +398,7 @@ group :ed25519 do
end end
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly-proto', '~> 0.39.0', require: 'gitaly' gem 'gitaly-proto', '~> 0.41.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 0.3.15', require: false
......
...@@ -274,7 +274,7 @@ GEM ...@@ -274,7 +274,7 @@ GEM
po_to_json (>= 1.0.0) po_to_json (>= 1.0.0)
rails (>= 3.2.0) rails (>= 3.2.0)
gherkin-ruby (0.3.2) gherkin-ruby (0.3.2)
gitaly-proto (0.39.0) gitaly-proto (0.41.0)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
grpc (~> 1.0) grpc (~> 1.0)
github-linguist (4.7.6) github-linguist (4.7.6)
...@@ -1023,7 +1023,7 @@ DEPENDENCIES ...@@ -1023,7 +1023,7 @@ DEPENDENCIES
gettext (~> 3.2.2) gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0) gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.39.0) gitaly-proto (~> 0.41.0)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2) gitlab-markup (~> 1.6.2)
......
## GitLab Core Team & GitLab Inc. Contribution Process ## GitLab core team & GitLab Inc. contribution process
--- ---
......
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
/* 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'; import { isInIssuePage, updateTooltipTitle } from './lib/utils/common_utils';
import Flash from './flash';
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'; const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
......
/* global Flash */ import Flash from '../flash';
import BalsamiqViewer from './balsamiq/balsamiq_viewer'; import BalsamiqViewer from './balsamiq/balsamiq_viewer';
function onError() { function onError() {
const flash = new window.Flash('Balsamiq file could not be loaded.'); const flash = new Flash('Balsamiq file could not be loaded.');
return flash; return flash;
} }
......
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
/* global Flash */ import Flash from '../flash';
import FileTemplateTypeSelector from './template_selectors/type_selector'; import FileTemplateTypeSelector from './template_selectors/type_selector';
import BlobCiYamlSelector from './template_selectors/ci_yaml_selector'; import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
import DockerfileSelector from './template_selectors/dockerfile_selector'; import DockerfileSelector from './template_selectors/dockerfile_selector';
......
/* global Flash */ import Flash from '../../flash';
import { handleLocationHash } from '../../lib/utils/common_utils'; import { handleLocationHash } from '../../lib/utils/common_utils';
export default class BlobViewer { export default class BlobViewer {
......
/* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren */ /* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren */
/* global BoardService */ /* global BoardService */
/* global Flash */
import _ from 'underscore'; import _ from 'underscore';
import Vue from 'vue'; import Vue from 'vue';
import VueResource from 'vue-resource'; import VueResource from 'vue-resource';
import Flash from '../flash';
import FilteredSearchBoards from './filtered_search_boards'; import FilteredSearchBoards from './filtered_search_boards';
import eventHub from './eventhub'; import eventHub from './eventhub';
import './models/issue'; import './models/issue';
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
/* global MilestoneSelect */ /* global MilestoneSelect */
/* global LabelsSelect */ /* global LabelsSelect */
/* global Sidebar */ /* global Sidebar */
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../flash';
import eventHub from '../../sidebar/event_hub'; import eventHub from '../../sidebar/event_hub';
import AssigneeTitle from '../../sidebar/components/assignees/assignee_title'; import AssigneeTitle from '../../sidebar/components/assignees/assignee_title';
import Assignees from '../../sidebar/components/assignees/assignees'; import Assignees from '../../sidebar/components/assignees/assignees';
......
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../../flash';
import './lists_dropdown'; import './lists_dropdown';
const ModalStore = gl.issueBoards.ModalStore; const ModalStore = gl.issueBoards.ModalStore;
......
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../../flash';
const Store = gl.issueBoards.BoardsStore; const Store = gl.issueBoards.BoardsStore;
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-unused-vars, no-return-assign, max-len */ /* eslint-disable func-names, prefer-arrow-callback, no-return-assign */
import { visitUrl } from './lib/utils/url_utility'; import { visitUrl } from './lib/utils/url_utility';
import { convertPermissionToBoolean } from './lib/utils/common_utils'; import { convertPermissionToBoolean } from './lib/utils/common_utils';
window.BuildArtifacts = (function() { export default class BuildArtifacts {
function BuildArtifacts() { constructor() {
this.disablePropagation(); this.disablePropagation();
this.setupEntryClick(); this.setupEntryClick();
this.setupTooltips(); this.setupTooltips();
} }
// eslint-disable-next-line class-methods-use-this
BuildArtifacts.prototype.disablePropagation = function() { disablePropagation() {
$('.top-block').on('click', '.download', function(e) { $('.top-block').on('click', '.download', function (e) {
return e.stopPropagation(); return e.stopPropagation();
}); });
return $('.tree-holder').on('click', 'tr[data-link] a', function(e) { return $('.tree-holder').on('click', 'tr[data-link] a', function (e) {
return e.stopImmediatePropagation(); return e.stopImmediatePropagation();
}); });
}; }
// eslint-disable-next-line class-methods-use-this
BuildArtifacts.prototype.setupEntryClick = function() { setupEntryClick() {
return $('.tree-holder').on('click', 'tr[data-link]', function(e) { return $('.tree-holder').on('click', 'tr[data-link]', function () {
visitUrl(this.dataset.link, convertPermissionToBoolean(this.dataset.externalLink)); visitUrl(this.dataset.link, convertPermissionToBoolean(this.dataset.externalLink));
}); });
}; }
// eslint-disable-next-line class-methods-use-this
BuildArtifacts.prototype.setupTooltips = function() { setupTooltips() {
$('.js-artifact-tree-tooltip').tooltip({ $('.js-artifact-tree-tooltip').tooltip({
placement: 'bottom', placement: 'bottom',
// Stop the tooltip from hiding when we stop hovering the element directly // Stop the tooltip from hiding when we stop hovering the element directly
...@@ -41,7 +41,5 @@ window.BuildArtifacts = (function() { ...@@ -41,7 +41,5 @@ window.BuildArtifacts = (function() {
.on('mouseleave', (e) => { .on('mouseleave', (e) => {
$(e.currentTarget).find('.js-artifact-tree-tooltip').tooltip('hide'); $(e.currentTarget).find('.js-artifact-tree-tooltip').tooltip('hide');
}); });
}; }
}
return BuildArtifacts;
})();
/* eslint-disable func-names, prefer-arrow-callback, space-before-function-paren */ /* eslint-disable func-names*/
$(function() { export default function handleRevealVariables() {
$('.reveal-variables').off('click').on('click', function() { $('.js-reveal-variables')
$('.js-build-variables').toggle(); .off('click')
$(this).hide(); .on('click', function () {
}); $('.js-build-variables').toggle();
}); $(this).hide();
});
}
export default class CILintEditor {
window.gl = window.gl || {};
class CILintEditor {
constructor() { constructor() {
this.editor = window.ace.edit('ci-editor'); this.editor = window.ace.edit('ci-editor');
this.textarea = document.querySelector('#content'); this.textarea = document.querySelector('#content');
...@@ -13,5 +10,3 @@ class CILintEditor { ...@@ -13,5 +10,3 @@ class CILintEditor {
}); });
} }
} }
gl.CILintEditor = CILintEditor;
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Flash */ import Flash from './flash';
import DropLab from './droplab/drop_lab'; import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter'; import ISetter from './droplab/plugins/input_setter';
......
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import Flash from '../flash';
import Translate from '../vue_shared/translate'; import Translate from '../vue_shared/translate';
import banner from './components/banner.vue'; import banner from './components/banner.vue';
import stageCodeComponent from './components/stage_code_component.vue'; import stageCodeComponent from './components/stage_code_component.vue';
......
<script> <script>
/* global Flash */ import Flash from '../../flash';
import eventHub from '../eventhub'; import eventHub from '../eventhub';
import DeployKeysService from '../service'; import DeployKeysService from '../service';
import DeployKeysStore from '../store'; import DeployKeysStore from '../store';
......
/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, max-len */ /* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, max-len */
/* global CommentsStore */ /* global CommentsStore */
/* global ResolveService */ /* global ResolveService */
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../flash';
const ResolveBtn = Vue.extend({ const ResolveBtn = Vue.extend({
props: { props: {
......
/* global Flash */
/* global CommentsStore */ /* global CommentsStore */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../flash';
import '../../vue_shared/vue_resource_interceptor'; import '../../vue_shared/vue_resource_interceptor';
window.gl = window.gl || {}; window.gl = window.gl || {};
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
/* global NotificationsDropdown */ /* global NotificationsDropdown */
/* global GroupAvatar */ /* global GroupAvatar */
/* global LineHighlighter */ /* global LineHighlighter */
/* global BuildArtifacts */ import BuildArtifacts from './build_artifacts';
import CILintEditor from './ci_lint_editor';
/* global GroupsSelect */ /* global GroupsSelect */
/* global Search */ /* global Search */
/* global Admin */ /* global Admin */
...@@ -28,7 +29,8 @@ ...@@ -28,7 +29,8 @@
/* global ProjectNew */ /* global ProjectNew */
/* global ProjectShow */ /* global ProjectShow */
/* global ProjectImport */ /* global ProjectImport */
/* global Labels */ import Labels from './labels';
import LabelManager from './label_manager';
/* global Shortcuts */ /* global Shortcuts */
/* global ShortcutsFindFile */ /* global ShortcutsFindFile */
/* global Sidebar */ /* global Sidebar */
...@@ -78,6 +80,9 @@ import initChangesDropdown from './init_changes_dropdown'; ...@@ -78,6 +80,9 @@ import initChangesDropdown from './init_changes_dropdown';
import AbuseReports from './abuse_reports'; import AbuseReports from './abuse_reports';
import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils'; import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils';
import AjaxLoadingSpinner from './ajax_loading_spinner'; import AjaxLoadingSpinner from './ajax_loading_spinner';
import GlFieldErrors from './gl_field_errors';
import GLForm from './gl_form';
import U2FAuthenticate from './u2f/authenticate';
(function() { (function() {
var Dispatcher; var Dispatcher;
...@@ -90,8 +95,8 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -90,8 +95,8 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
} }
Dispatcher.prototype.initPageScripts = function() { Dispatcher.prototype.initPageScripts = function() {
var page, path, shortcut_handler, fileBlobPermalinkUrlElement, fileBlobPermalinkUrl; var path, shortcut_handler, fileBlobPermalinkUrlElement, fileBlobPermalinkUrl;
page = $('body').attr('data-page'); const page = $('body').attr('data-page');
if (!page) { if (!page) {
return false; return false;
} }
...@@ -228,7 +233,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -228,7 +233,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
case 'groups:milestones:update': case 'groups:milestones:update':
new ZenMode(); new ZenMode();
new gl.DueDateSelectors(); new gl.DueDateSelectors();
new gl.GLForm($('.milestone-form'), true); new GLForm($('.milestone-form'), true);
break; break;
case 'projects:compare:show': case 'projects:compare:show':
new gl.Diff(); new gl.Diff();
...@@ -245,7 +250,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -245,7 +250,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
case 'projects:issues:new': case 'projects:issues:new':
case 'projects:issues:edit': case 'projects:issues:edit':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
new gl.GLForm($('.issue-form'), true); new GLForm($('.issue-form'), true);
new IssuableForm($('.issue-form')); new IssuableForm($('.issue-form'));
new LabelsSelect(); new LabelsSelect();
new MilestoneSelect(); new MilestoneSelect();
...@@ -269,7 +274,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -269,7 +274,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
case 'projects:merge_requests:edit': case 'projects:merge_requests:edit':
new gl.Diff(); new gl.Diff();
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
new gl.GLForm($('.merge-request-form'), true); new GLForm($('.merge-request-form'), true);
new IssuableForm($('.merge-request-form')); new IssuableForm($('.merge-request-form'));
new LabelsSelect(); new LabelsSelect();
new MilestoneSelect(); new MilestoneSelect();
...@@ -278,7 +283,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -278,7 +283,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
break; break;
case 'projects:tags:new': case 'projects:tags:new':
new ZenMode(); new ZenMode();
new gl.GLForm($('.tag-form'), true); new GLForm($('.tag-form'), true);
new RefSelectDropdown($('.js-branch-select')); new RefSelectDropdown($('.js-branch-select'));
break; break;
case 'projects:snippets:show': case 'projects:snippets:show':
...@@ -288,17 +293,17 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -288,17 +293,17 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
case 'projects:snippets:edit': case 'projects:snippets:edit':
case 'projects:snippets:create': case 'projects:snippets:create':
case 'projects:snippets:update': case 'projects:snippets:update':
new gl.GLForm($('.snippet-form'), true); new GLForm($('.snippet-form'), true);
break; break;
case 'snippets:new': case 'snippets:new':
case 'snippets:edit': case 'snippets:edit':
case 'snippets:create': case 'snippets:create':
case 'snippets:update': case 'snippets:update':
new gl.GLForm($('.snippet-form'), false); new GLForm($('.snippet-form'), false);
break; break;
case 'projects:releases:edit': case 'projects:releases:edit':
new ZenMode(); new ZenMode();
new gl.GLForm($('.release-form'), true); new GLForm($('.release-form'), true);
break; break;
case 'projects:merge_requests:show': case 'projects:merge_requests:show':
new gl.Diff(); new gl.Diff();
...@@ -457,7 +462,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -457,7 +462,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
case 'groups:labels:index': case 'groups:labels:index':
case 'projects:labels:index': case 'projects:labels:index':
if ($('.prioritized-labels').length) { if ($('.prioritized-labels').length) {
new gl.LabelManager(); new LabelManager();
} }
$('.label-subscription').each((i, el) => { $('.label-subscription').each((i, el) => {
const $el = $(el); const $el = $(el);
...@@ -505,7 +510,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -505,7 +510,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
break; break;
case 'ci:lints:create': case 'ci:lints:create':
case 'ci:lints:show': case 'ci:lints:show':
new gl.CILintEditor(); new CILintEditor();
break; break;
case 'users:show': case 'users:show':
new UserCallout(); new UserCallout();
...@@ -535,14 +540,16 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -535,14 +540,16 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
case 'sessions': case 'sessions':
case 'omniauth_callbacks': case 'omniauth_callbacks':
if (!gon.u2f) break; if (!gon.u2f) break;
gl.u2fAuthenticate = new gl.U2FAuthenticate( const u2fAuthenticate = new U2FAuthenticate(
$('#js-authenticate-u2f'), $('#js-authenticate-u2f'),
'#js-login-u2f-form', '#js-login-u2f-form',
gon.u2f, gon.u2f,
document.querySelector('#js-login-2fa-device'), document.querySelector('#js-login-2fa-device'),
document.querySelector('.js-2fa-form'), document.querySelector('.js-2fa-form'),
); );
gl.u2fAuthenticate.start(); u2fAuthenticate.start();
// needed in rspec
gl.u2fAuthenticate = u2fAuthenticate;
case 'admin': case 'admin':
new Admin(); new Admin();
switch (path[1]) { switch (path[1]) {
...@@ -602,7 +609,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -602,7 +609,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
new Wikis(); new Wikis();
shortcut_handler = new ShortcutsWiki(); shortcut_handler = new ShortcutsWiki();
new ZenMode(); new ZenMode();
new gl.GLForm($('.wiki-form'), true); new GLForm($('.wiki-form'), true);
break; break;
case 'snippets': case 'snippets':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
...@@ -627,12 +634,6 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -627,12 +634,6 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
} }
break; break;
case 'users':
const action = path[1];
import(/* webpackChunkName: 'user_profile' */ './users')
.then(user => user.default(action))
.catch(() => {});
break;
} }
// If we haven't installed a custom shortcut handler, install the default one // If we haven't installed a custom shortcut handler, install the default one
if (!shortcut_handler) { if (!shortcut_handler) {
...@@ -653,7 +654,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner'; ...@@ -653,7 +654,7 @@ import AjaxLoadingSpinner from './ajax_loading_spinner';
Dispatcher.prototype.initFieldErrors = function() { Dispatcher.prototype.initFieldErrors = function() {
$('.gl-show-field-errors').each((i, form) => { $('.gl-show-field-errors').each((i, form) => {
new gl.GlFieldErrors(form); new GlFieldErrors(form);
}); });
}; };
......
...@@ -237,9 +237,12 @@ window.DropzoneInput = (function() { ...@@ -237,9 +237,12 @@ window.DropzoneInput = (function() {
}; };
const insertToTextArea = function(filename, url) { const insertToTextArea = function(filename, url) {
return $(child).val(function(index, val) { const $child = $(child);
$child.val(function(index, val) {
return val.replace(`{{${filename}}}`, url); return val.replace(`{{${filename}}}`, url);
}); });
$child.trigger('change');
}; };
const appendToTextArea = function(url) { const appendToTextArea = function(url) {
......
<script> <script>
/* global Flash */
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Flash from '../../flash';
import EnvironmentsService from '../services/environments_service'; import EnvironmentsService from '../services/environments_service';
import environmentTable from './environments_table.vue'; import environmentTable from './environments_table.vue';
import EnvironmentsStore from '../stores/environments_store'; import EnvironmentsStore from '../stores/environments_store';
......
<script> <script>
/* global Flash */
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Flash from '../../flash';
import EnvironmentsService from '../services/environments_service'; import EnvironmentsService from '../services/environments_service';
import environmentTable from '../components/environments_table.vue'; import environmentTable from '../components/environments_table.vue';
import EnvironmentsStore from '../stores/environments_store'; import EnvironmentsStore from '../stores/environments_store';
......
/* global Flash */ import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax';
import Ajax from '~/droplab/plugins/ajax'; import Filter from '../droplab/plugins/filter';
import Filter from '~/droplab/plugins/filter';
import './filtered_search_dropdown'; import './filtered_search_dropdown';
class DropdownEmoji extends gl.FilteredSearchDropdown { class DropdownEmoji extends gl.FilteredSearchDropdown {
......
/* global Flash */ import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax';
import Ajax from '~/droplab/plugins/ajax'; import Filter from '../droplab/plugins/filter';
import Filter from '~/droplab/plugins/filter';
import './filtered_search_dropdown'; import './filtered_search_dropdown';
class DropdownNonUser extends gl.FilteredSearchDropdown { class DropdownNonUser extends gl.FilteredSearchDropdown {
......
/* global Flash */ import Flash from '../flash';
import AjaxFilter from '../droplab/plugins/ajax_filter';
import AjaxFilter from '~/droplab/plugins/ajax_filter';
import './filtered_search_dropdown'; import './filtered_search_dropdown';
import { addClassIfElementExists } from '../lib/utils/dom_utils'; import { addClassIfElementExists } from '../lib/utils/dom_utils';
......
import Flash from '../flash';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
import RecentSearchesRoot from './recent_searches_root'; import RecentSearchesRoot from './recent_searches_root';
import RecentSearchesStore from './stores/recent_searches_store'; import RecentSearchesStore from './stores/recent_searches_store';
...@@ -36,7 +37,7 @@ class FilteredSearchManager { ...@@ -36,7 +37,7 @@ class FilteredSearchManager {
.catch((error) => { .catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined; if (error.name === 'RecentSearchesServiceError') return undefined;
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new window.Flash('An error occurred while parsing recent searches'); new Flash('An error occurred while parsing recent searches');
// Gracefully fail to empty array // Gracefully fail to empty array
return []; return [];
}) })
......
import AjaxCache from '../lib/utils/ajax_cache'; import AjaxCache from '../lib/utils/ajax_cache';
import '../flash'; /* global Flash */ import Flash from '../flash';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
import UsersCache from '../lib/utils/users_cache'; import UsersCache from '../lib/utils/users_cache';
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, no-param-reassign, quotes, quote-props, prefer-template, comma-dangle, max-len */ import _ from 'underscore';
window.Flash = (function() { const hideFlash = (flashEl, fadeTransition = true) => {
var hideFlash; if (fadeTransition) {
Object.assign(flashEl.style, {
transition: 'opacity .3s',
opacity: '0',
});
}
hideFlash = function() { flashEl.addEventListener('transitionend', () => {
return $(this).fadeOut(); flashEl.remove();
}; }, {
once: true,
passive: true,
});
/** if (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
* Flash banner supports different types of Flash configurations };
* along with ability to provide actionConfig which can be used to show
* additional action or link on banner next to message
*
* @param {String} message Flash message
* @param {String} type Type of Flash, it can be `notice` or `alert` (default)
* @param {Object} parent Reference to Parent element under which Flash needs to appear
* @param {Object} actionConfig Map of config to show action on banner
* @param {String} href URL to which action link should point (default '#')
* @param {String} title Title of action
* @param {Function} clickHandler Method to call when action is clicked on
*/
function Flash(message, type, parent, actionConfig) {
var flash, textDiv, actionLink;
if (type == null) {
type = 'alert';
}
if (parent == null) {
parent = null;
}
if (parent) {
this.flashContainer = parent.find('.flash-container');
} else {
this.flashContainer = $('.flash-container-page');
}
this.flashContainer.html('');
flash = $('<div/>', {
"class": "flash-" + type
});
flash.on('click', hideFlash);
textDiv = $('<div/>', {
"class": 'flash-text',
text: message
});
textDiv.appendTo(flash);
if (actionConfig) { const createAction = config => `
const actionLinkConfig = { <a
class: 'flash-action', href="${config.href || '#'}"
href: actionConfig.href || '#', class="flash-action"
text: actionConfig.title ${config.href ? '' : 'role="button"'}
}; >
${_.escape(config.title)}
</a>
`;
if (!actionConfig.href) { const createFlashEl = (message, type, isInContentWrapper = false) => `
actionLinkConfig.role = 'button'; <div
} class="flash-${type}"
>
<div
class="flash-text ${isInContentWrapper ? 'container-fluid container-limited' : ''}"
>
${_.escape(message)}
</div>
</div>
`;
actionLink = $('<a/>', actionLinkConfig); /*
* Flash banner supports different types of Flash configurations
* along with ability to provide actionConfig which can be used to show
* additional action or link on banner next to message
*
* @param {String} message Flash message text
* @param {String} type Type of Flash, it can be `notice` or `alert` (default)
* @param {Object} parent Reference to parent element under which Flash needs to appear
* @param {Object} actonConfig Map of config to show action on banner
* @param {String} href URL to which action config should point to (default: '#')
* @param {String} title Title of action
* @param {Function} clickHandler Method to call when action is clicked on
* @param {Boolean} fadeTransition Boolean to determine whether to fade the alert out
*/
const createFlash = function createFlash(
message,
type = 'alert',
parent = document,
actionConfig = null,
fadeTransition = true,
) {
const flashContainer = parent.querySelector('.flash-container');
actionLink.appendTo(flash); if (!flashContainer) return null;
this.flashContainer.on('click', '.flash-action', actionConfig.clickHandler);
} const isInContentWrapper = flashContainer.parentNode.classList.contains('content-wrapper');
if (this.flashContainer.parent().hasClass('content-wrapper')) {
textDiv.addClass('container-fluid container-limited'); flashContainer.innerHTML = createFlashEl(message, type, isInContentWrapper);
const flashEl = flashContainer.querySelector(`.flash-${type}`);
flashEl.addEventListener('click', () => hideFlash(flashEl, fadeTransition));
if (actionConfig) {
flashEl.innerHTML += createAction(actionConfig);
if (actionConfig.clickHandler) {
flashEl.querySelector('.flash-action').addEventListener('click', e => actionConfig.clickHandler(e));
} }
flash.appendTo(this.flashContainer);
this.flashContainer.show();
} }
return Flash; flashContainer.style.display = 'block';
})();
return flashContainer;
};
export {
createFlash as default,
createFlashEl,
createAction,
hideFlash,
};
window.Flash = createFlash;
...@@ -54,7 +54,7 @@ const inputErrorClass = 'gl-field-error-outline'; ...@@ -54,7 +54,7 @@ const inputErrorClass = 'gl-field-error-outline';
const errorAnchorSelector = '.gl-field-error-anchor'; const errorAnchorSelector = '.gl-field-error-anchor';
const ignoreInputSelector = '.gl-field-error-ignore'; const ignoreInputSelector = '.gl-field-error-ignore';
class GlFieldError { export default class GlFieldError {
constructor({ input, formErrors }) { constructor({ input, formErrors }) {
this.inputElement = $(input); this.inputElement = $(input);
this.inputDomElement = this.inputElement.get(0); this.inputDomElement = this.inputElement.get(0);
...@@ -159,6 +159,3 @@ class GlFieldError { ...@@ -159,6 +159,3 @@ class GlFieldError {
this.fieldErrorElement.hide(); this.fieldErrorElement.hide();
} }
} }
window.gl = window.gl || {};
window.gl.GlFieldError = GlFieldError;
/* eslint-disable comma-dangle, class-methods-use-this, max-len, space-before-function-paren, arrow-parens, no-param-reassign */ import GlFieldError from './gl_field_error';
import './gl_field_error';
const customValidationFlag = 'gl-field-error-ignore'; const customValidationFlag = 'gl-field-error-ignore';
class GlFieldErrors { export default class GlFieldErrors {
constructor(form) { constructor(form) {
this.form = $(form); this.form = $(form);
this.state = { this.state = {
inputs: [], inputs: [],
valid: false valid: false,
}; };
this.initValidators(); this.initValidators();
} }
initValidators () { initValidators() {
// register selectors here as needed // register selectors here as needed
const validateSelectors = [':text', ':password', '[type=email]'] const validateSelectors = [':text', ':password', '[type=email]']
.map((selector) => `input${selector}`).join(','); .map(selector => `input${selector}`).join(',');
this.state.inputs = this.form.find(validateSelectors).toArray() this.state.inputs = this.form.find(validateSelectors).toArray()
.filter((input) => !input.classList.contains(customValidationFlag)) .filter(input => !input.classList.contains(customValidationFlag))
.map((input) => new window.gl.GlFieldError({ input, formErrors: this })); .map(input => new GlFieldError({ input, formErrors: this }));
this.form.on('submit', this.catchInvalidFormSubmit); this.form.on('submit', GlFieldErrors.catchInvalidFormSubmit);
} }
/* Neccessary to prevent intercept and override invalid form submit /* Neccessary to prevent intercept and override invalid form submit
* because Safari & iOS quietly allow form submission when form is invalid * because Safari & iOS quietly allow form submission when form is invalid
* and prevents disabling of invalid submit button by application.js */ * and prevents disabling of invalid submit button by application.js */
catchInvalidFormSubmit (event) { static catchInvalidFormSubmit(e) {
const $form = $(event.currentTarget); const $form = $(e.currentTarget);
if (!$form.attr('novalidate')) { if (!$form.attr('novalidate')) {
if (!event.currentTarget.checkValidity()) { if (!e.currentTarget.checkValidity()) {
event.preventDefault(); e.preventDefault();
event.stopPropagation(); e.stopPropagation();
} }
} }
} }
...@@ -50,11 +48,9 @@ class GlFieldErrors { ...@@ -50,11 +48,9 @@ class GlFieldErrors {
}); });
} }
focusOnFirstInvalid () { focusOnFirstInvalid() {
const firstInvalid = this.state.inputs.filter((input) => !input.inputDomElement.validity.valid)[0]; const firstInvalid = this.state.inputs
.filter(input => !input.inputDomElement.validity.valid)[0];
firstInvalid.inputElement.focus(); firstInvalid.inputElement.focus();
} }
} }
window.gl = window.gl || {};
window.gl.GlFieldErrors = GlFieldErrors;
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-new, max-len */
/* global GitLab */
/* global DropzoneInput */ /* global DropzoneInput */
/* global autosize */ /* global autosize */
import GfmAutoComplete from './gfm_auto_complete'; import GfmAutoComplete from './gfm_auto_complete';
window.gl = window.gl || {}; export default class GLForm {
constructor(form, enableGFM = false) {
function GLForm(form, enableGFM = false) { this.form = form;
this.form = form; this.textarea = this.form.find('textarea.js-gfm-input');
this.textarea = this.form.find('textarea.js-gfm-input'); this.enableGFM = enableGFM;
this.enableGFM = enableGFM; // Before we start, we should clean up any previous data for this form
// Before we start, we should clean up any previous data for this form this.destroy();
this.destroy(); // Setup the form
// Setup the form this.setupForm();
this.setupForm(); this.form.data('gl-form', this);
this.form.data('gl-form', this);
}
GLForm.prototype.destroy = function() {
// Clean form listeners
this.clearEventListeners();
if (this.autoComplete) {
this.autoComplete.destroy();
} }
return this.form.data('gl-form', null);
};
GLForm.prototype.setupForm = function() { destroy() {
var isNewForm; // Clean form listeners
isNewForm = this.form.is(':not(.gfm-form)'); this.clearEventListeners();
this.form.removeClass('js-new-note-form'); if (this.autoComplete) {
if (isNewForm) { this.autoComplete.destroy();
this.form.find('.div-dropzone').remove(); }
this.form.addClass('gfm-form'); this.form.data('gl-form', null);
// remove notify commit author checkbox for non-commit notes
gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button, .js-note-new-discussion'));
this.autoComplete = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
this.autoComplete.setup(this.form.find('.js-gfm-input'), {
emojis: true,
members: this.enableGFM,
issues: this.enableGFM,
milestones: this.enableGFM,
mergeRequests: this.enableGFM,
labels: this.enableGFM,
});
new DropzoneInput(this.form);
autosize(this.textarea);
} }
// form and textarea event listeners
this.addEventListeners();
gl.text.init(this.form);
// hide discard button
this.form.find('.js-note-discard').hide();
this.form.show();
if (this.isAutosizeable) this.setupAutosize();
};
GLForm.prototype.setupAutosize = function () { setupForm() {
this.textarea.off('autosize:resized') const isNewForm = this.form.is(':not(.gfm-form)');
.on('autosize:resized', this.setHeightData.bind(this)); this.form.removeClass('js-new-note-form');
if (isNewForm) {
this.form.find('.div-dropzone').remove();
this.form.addClass('gfm-form');
// remove notify commit author checkbox for non-commit notes
gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button, .js-note-new-discussion'));
this.autoComplete = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
this.autoComplete.setup(this.form.find('.js-gfm-input'), {
emojis: true,
members: this.enableGFM,
issues: this.enableGFM,
milestones: this.enableGFM,
mergeRequests: this.enableGFM,
labels: this.enableGFM,
});
new DropzoneInput(this.form); // eslint-disable-line no-new
autosize(this.textarea);
}
// form and textarea event listeners
this.addEventListeners();
gl.text.init(this.form);
// hide discard button
this.form.find('.js-note-discard').hide();
this.form.show();
if (this.isAutosizeable) this.setupAutosize();
}
this.textarea.off('mouseup.autosize') setupAutosize() {
.on('mouseup.autosize', this.destroyAutosize.bind(this)); this.textarea.off('autosize:resized')
.on('autosize:resized', this.setHeightData.bind(this));
setTimeout(() => { this.textarea.off('mouseup.autosize')
autosize(this.textarea); .on('mouseup.autosize', this.destroyAutosize.bind(this));
this.textarea.css('resize', 'vertical');
}, 0);
};
GLForm.prototype.setHeightData = function () { setTimeout(() => {
this.textarea.data('height', this.textarea.outerHeight()); autosize(this.textarea);
}; this.textarea.css('resize', 'vertical');
}, 0);
}
GLForm.prototype.destroyAutosize = function () { setHeightData() {
const outerHeight = this.textarea.outerHeight(); this.textarea.data('height', this.textarea.outerHeight());
}
if (this.textarea.data('height') === outerHeight) return; destroyAutosize() {
const outerHeight = this.textarea.outerHeight();
autosize.destroy(this.textarea); if (this.textarea.data('height') === outerHeight) return;
this.textarea.data('height', outerHeight); autosize.destroy(this.textarea);
this.textarea.outerHeight(outerHeight);
this.textarea.css('max-height', window.outerHeight);
};
GLForm.prototype.clearEventListeners = function() { this.textarea.data('height', outerHeight);
this.textarea.off('focus'); this.textarea.outerHeight(outerHeight);
this.textarea.off('blur'); this.textarea.css('max-height', window.outerHeight);
return gl.text.removeListeners(this.form); }
};
GLForm.prototype.addEventListeners = function() { clearEventListeners() {
this.textarea.on('focus', function() { this.textarea.off('focus');
return $(this).closest('.md-area').addClass('is-focused'); this.textarea.off('blur');
}); gl.text.removeListeners(this.form);
return this.textarea.on('blur', function() { }
return $(this).closest('.md-area').removeClass('is-focused');
});
};
window.gl.GLForm = GLForm; addEventListeners() {
this.textarea.on('focus', function focusTextArea() {
$(this).closest('.md-area').addClass('is-focused');
});
this.textarea.on('blur', function blurTextArea() {
$(this).closest('.md-area').removeClass('is-focused');
});
}
}
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../flash';
import GroupFilterableList from './groups_filterable_list'; import GroupFilterableList from './groups_filterable_list';
import GroupsComponent from './components/groups.vue'; import GroupsComponent from './components/groups.vue';
import GroupFolder from './components/group_folder.vue'; import GroupFolder from './components/group_folder.vue';
......
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var */ import { highCountTrim } from '~/lib/utils/text_utility';
$(document).on('todo:toggle', function(e, count) { /**
var $todoPendingCount = $('.todos-count'); * Updates todo counter when todos are toggled.
$todoPendingCount.text(gl.text.highCountTrim(count)); * When count is 0, we hide the badge.
$todoPendingCount.toggleClass('hidden', count === 0); *
* @param {jQuery.Event} e
* @param {String} count
*/
$(document).on('todo:toggle', (e, count) => {
const parsedCount = parseInt(count, 10);
const $todoPendingCount = $('.todos-count');
$todoPendingCount.text(highCountTrim(parsedCount));
$todoPendingCount.toggleClass('hidden', parsedCount === 0);
}); });
/* global Flash */ import Flash from '../flash';
export default class IntegrationSettingsForm { export default class IntegrationSettingsForm {
constructor(formSelector) { constructor(formSelector) {
...@@ -102,7 +102,7 @@ export default class IntegrationSettingsForm { ...@@ -102,7 +102,7 @@ export default class IntegrationSettingsForm {
}) })
.done((res) => { .done((res) => {
if (res.error) { if (res.error) {
new Flash(`${res.message} ${res.service_response}`, null, null, { new Flash(`${res.message} ${res.service_response}`, 'alert', document, {
title: 'Save anyway', title: 'Save anyway',
clickHandler: (e) => { clickHandler: (e) => {
e.preventDefault(); e.preventDefault();
......
/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */ /* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */
/* global IssuableIndex */ /* global IssuableIndex */
/* global Flash */
import _ from 'underscore'; import _ from 'underscore';
import Flash from './flash';
export default { export default {
init({ container, form, issues, prefixId } = {}) { init({ container, form, issues, prefixId } = {}) {
......
/* 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 */ /* 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 */
/* global Flash */
import 'vendor/jquery.waitforimages'; import 'vendor/jquery.waitforimages';
import '~/lib/utils/text_utility'; import '~/lib/utils/text_utility';
import './flash'; import Flash from './flash';
import TaskList from './task_list'; import TaskList from './task_list';
import CreateMergeRequestDropdown from './create_merge_request_dropdown'; import CreateMergeRequestDropdown from './create_merge_request_dropdown';
import IssuablesHelper from './helpers/issuables_helper'; import IssuablesHelper from './helpers/issuables_helper';
......
<script> <script>
/* global Flash */
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Poll from '../../lib/utils/poll'; import Poll from '../../lib/utils/poll';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
...@@ -153,7 +152,7 @@ export default { ...@@ -153,7 +152,7 @@ export default {
}) })
.catch(() => { .catch(() => {
eventHub.$emit('close.form'); eventHub.$emit('close.form');
return new Flash('Error updating issue'); window.Flash('Error updating issue');
}); });
}, },
deleteIssuable() { deleteIssuable() {
...@@ -167,7 +166,7 @@ export default { ...@@ -167,7 +166,7 @@ export default {
}) })
.catch(() => { .catch(() => {
eventHub.$emit('close.form'); eventHub.$emit('close.form');
return new Flash('Error deleting issue'); window.Flash('Error deleting issue');
}); });
}, },
}, },
......
<script> <script>
/* global Flash */
import updateMixin from '../../mixins/update'; import updateMixin from '../../mixins/update';
import markdownField from '../../../vue_shared/components/markdown/field.vue'; import markdownField from '../../../vue_shared/components/markdown/field.vue';
......
/* eslint-disable func-names, wrap-iife, no-use-before-define,
consistent-return, prefer-rest-params */
import _ from 'underscore'; import _ from 'underscore';
import bp from './breakpoints'; import bp from './breakpoints';
import { bytesToKiB } from './lib/utils/number_utils'; import { bytesToKiB } from './lib/utils/number_utils';
import { setCiStatusFavicon } from './lib/utils/common_utils'; import { setCiStatusFavicon } from './lib/utils/common_utils';
window.Build = (function () { export default class Job {
Build.timeout = null; constructor(options) {
Build.state = null; this.timeout = null;
this.state = null;
function Build(options) {
this.options = options || $('.js-build-options').data(); this.options = options || $('.js-build-options').data();
this.pageUrl = this.options.pageUrl; this.pageUrl = this.options.pageUrl;
...@@ -19,9 +16,7 @@ window.Build = (function () { ...@@ -19,9 +16,7 @@ window.Build = (function () {
this.$document = $(document); this.$document = $(document);
this.logBytes = 0; this.logBytes = 0;
this.hasBeenScrolled = false; this.hasBeenScrolled = false;
this.updateDropdown = this.updateDropdown.bind(this); this.updateDropdown = this.updateDropdown.bind(this);
this.getBuildTrace = this.getBuildTrace.bind(this);
this.$buildTrace = $('#build-trace'); this.$buildTrace = $('#build-trace');
this.$buildRefreshAnimation = $('.js-build-refresh'); this.$buildRefreshAnimation = $('.js-build-refresh');
...@@ -33,7 +28,7 @@ window.Build = (function () { ...@@ -33,7 +28,7 @@ window.Build = (function () {
this.$scrollTopBtn = $('.js-scroll-up'); this.$scrollTopBtn = $('.js-scroll-up');
this.$scrollBottomBtn = $('.js-scroll-down'); this.$scrollBottomBtn = $('.js-scroll-down');
clearTimeout(Build.timeout); clearTimeout(this.timeout);
this.initSidebar(); this.initSidebar();
this.populateJobs(this.buildStage); this.populateJobs(this.buildStage);
...@@ -85,7 +80,7 @@ window.Build = (function () { ...@@ -85,7 +80,7 @@ window.Build = (function () {
this.getBuildTrace(); this.getBuildTrace();
} }
Build.prototype.initAffixTopArea = function () { initAffixTopArea() {
/** /**
If the browser does not support position sticky, it returns the position as static. If the browser does not support position sticky, it returns the position as static.
If the browser does support sticky, then we allow the browser to handle it, if not If the browser does support sticky, then we allow the browser to handle it, if not
...@@ -100,13 +95,14 @@ window.Build = (function () { ...@@ -100,13 +95,14 @@ window.Build = (function () {
top: offsetTop, top: offsetTop,
}, },
}); });
}; }
Build.prototype.canScroll = function () { // eslint-disable-next-line class-methods-use-this
canScroll() {
return $(document).height() > $(window).height(); return $(document).height() > $(window).height();
}; }
Build.prototype.toggleScroll = function () { toggleScroll() {
const currentPosition = $(document).scrollTop(); const currentPosition = $(document).scrollTop();
const scrollHeight = $(document).height(); const scrollHeight = $(document).height();
...@@ -119,7 +115,7 @@ window.Build = (function () { ...@@ -119,7 +115,7 @@ window.Build = (function () {
this.toggleDisableButton(this.$scrollTopBtn, false); this.toggleDisableButton(this.$scrollTopBtn, false);
this.toggleDisableButton(this.$scrollBottomBtn, false); this.toggleDisableButton(this.$scrollBottomBtn, false);
} else if (currentPosition === 0) { } else if (currentPosition === 0) {
// User is at Top of Build Log // User is at Top of Log
this.toggleDisableButton(this.$scrollTopBtn, true); this.toggleDisableButton(this.$scrollTopBtn, true);
this.toggleDisableButton(this.$scrollBottomBtn, false); this.toggleDisableButton(this.$scrollBottomBtn, false);
...@@ -133,38 +129,40 @@ window.Build = (function () { ...@@ -133,38 +129,40 @@ window.Build = (function () {
this.toggleDisableButton(this.$scrollTopBtn, true); this.toggleDisableButton(this.$scrollTopBtn, true);
this.toggleDisableButton(this.$scrollBottomBtn, true); this.toggleDisableButton(this.$scrollBottomBtn, true);
} }
}; }
Build.prototype.scrollDown = function () { // eslint-disable-next-line class-methods-use-this
scrollDown() {
$(document).scrollTop($(document).height()); $(document).scrollTop($(document).height());
}; }
Build.prototype.scrollToBottom = function () { scrollToBottom() {
this.scrollDown(); this.scrollDown();
this.hasBeenScrolled = true; this.hasBeenScrolled = true;
this.toggleScroll(); this.toggleScroll();
}; }
Build.prototype.scrollToTop = function () { scrollToTop() {
$(document).scrollTop(0); $(document).scrollTop(0);
this.hasBeenScrolled = true; this.hasBeenScrolled = true;
this.toggleScroll(); this.toggleScroll();
}; }
Build.prototype.toggleDisableButton = function ($button, disable) { // eslint-disable-next-line class-methods-use-this
toggleDisableButton($button, disable) {
if (disable && $button.prop('disabled')) return; if (disable && $button.prop('disabled')) return;
$button.prop('disabled', disable); $button.prop('disabled', disable);
}; }
Build.prototype.toggleScrollAnimation = function (toggle) { toggleScrollAnimation(toggle) {
this.$scrollBottomBtn.toggleClass('animate', toggle); this.$scrollBottomBtn.toggleClass('animate', toggle);
}; }
Build.prototype.initSidebar = function () { initSidebar() {
this.$sidebar = $('.js-build-sidebar'); this.$sidebar = $('.js-build-sidebar');
}; }
Build.prototype.getBuildTrace = function () { getBuildTrace() {
return $.ajax({ return $.ajax({
url: `${this.pageUrl}/trace.json`, url: `${this.pageUrl}/trace.json`,
data: { state: this.state }, data: { state: this.state },
...@@ -204,7 +202,7 @@ window.Build = (function () { ...@@ -204,7 +202,7 @@ window.Build = (function () {
this.toggleScrollAnimation(false); this.toggleScrollAnimation(false);
} }
Build.timeout = setTimeout(() => { this.timeout = setTimeout(() => {
this.getBuildTrace(); this.getBuildTrace();
}, 4000); }, 4000);
} else { } else {
...@@ -225,14 +223,14 @@ window.Build = (function () { ...@@ -225,14 +223,14 @@ window.Build = (function () {
} }
}) })
.then(() => this.toggleScroll()); .then(() => this.toggleScroll());
}; }
// eslint-disable-next-line class-methods-use-this
Build.prototype.shouldHideSidebarForViewport = function () { shouldHideSidebarForViewport() {
const bootstrapBreakpoint = bp.getBreakpointSize(); const bootstrapBreakpoint = bp.getBreakpointSize();
return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
}; }
Build.prototype.toggleSidebar = function (shouldHide) { toggleSidebar(shouldHide) {
const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined; const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
const $toggleButton = $('.js-sidebar-build-toggle-header'); const $toggleButton = $('.js-sidebar-build-toggle-header');
...@@ -249,17 +247,17 @@ window.Build = (function () { ...@@ -249,17 +247,17 @@ window.Build = (function () {
} else { } else {
$toggleButton.removeClass('hidden'); $toggleButton.removeClass('hidden');
} }
}; }
Build.prototype.sidebarOnResize = function () { sidebarOnResize() {
this.toggleSidebar(this.shouldHideSidebarForViewport()); this.toggleSidebar(this.shouldHideSidebarForViewport());
}; }
Build.prototype.sidebarOnClick = function () { sidebarOnClick() {
if (this.shouldHideSidebarForViewport()) this.toggleSidebar(); if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
}; }
// eslint-disable-next-line class-methods-use-this, consistent-return
Build.prototype.updateArtifactRemoveDate = function () { updateArtifactRemoveDate() {
const $date = $('.js-artifacts-remove'); const $date = $('.js-artifacts-remove');
if ($date.length) { if ($date.length) {
const date = $date.text(); const date = $date.text();
...@@ -267,23 +265,21 @@ window.Build = (function () { ...@@ -267,23 +265,21 @@ window.Build = (function () {
gl.utils.timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '), gl.utils.timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '),
); );
} }
}; }
// eslint-disable-next-line class-methods-use-this
Build.prototype.populateJobs = function (stage) { populateJobs(stage) {
$('.build-job').hide(); $('.build-job').hide();
$(`.build-job[data-stage="${stage}"]`).show(); $(`.build-job[data-stage="${stage}"]`).show();
}; }
// eslint-disable-next-line class-methods-use-this
Build.prototype.updateStageDropdownText = function (stage) { updateStageDropdownText(stage) {
$('.stage-selection').text(stage); $('.stage-selection').text(stage);
}; }
Build.prototype.updateDropdown = function (e) { updateDropdown(e) {
e.preventDefault(); e.preventDefault();
const stage = e.currentTarget.text; const stage = e.currentTarget.text;
this.updateStageDropdownText(stage); this.updateStageDropdownText(stage);
this.populateJobs(stage); this.populateJobs(stage);
}; }
}
return Build;
})();
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import JobMediator from './job_details_mediator'; import JobMediator from './job_details_mediator';
import jobHeader from './components/header.vue'; import jobHeader from './components/header.vue';
......
/* global Flash */
/* global Build */ /* global Build */
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Flash from '../flash';
import Poll from '../lib/utils/poll'; import Poll from '../lib/utils/poll';
import JobStore from './stores/job_store'; import JobStore from './stores/job_store';
import JobService from './services/job_service'; import JobService from './services/job_service';
import '../build'; import Job from '../job';
import handleRevealVariables from '../build_variables';
export default class JobMediator { export default class JobMediator {
constructor(options = {}) { constructor(options = {}) {
...@@ -20,7 +21,8 @@ export default class JobMediator { ...@@ -20,7 +21,8 @@ export default class JobMediator {
} }
initBuildClass() { initBuildClass() {
this.build = new Build(); this.build = new Job();
handleRevealVariables();
} }
fetchJob() { fetchJob() {
......
/* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, max-len */ /* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, max-len */
/* global Flash */
/* global Sortable */ /* global Sortable */
((global) => { import Flash from './flash';
class LabelManager {
constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
this.otherLabels = otherLabels || $('.js-other-labels');
this.errorMessage = 'Unable to update label prioritization at this time';
this.emptyState = document.querySelector('#js-priority-labels-empty-state');
this.sortable = Sortable.create(this.prioritizedLabels.get(0), {
filter: '.empty-message',
forceFallback: true,
fallbackClass: 'is-dragging',
dataIdAttr: 'data-id',
onUpdate: this.onPrioritySortUpdate.bind(this),
});
this.bindEvents();
}
bindEvents() { export default class LabelManager {
this.prioritizedLabels.find('.btn-action').on('mousedown', this, this.onButtonActionClick); constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick); this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
} this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
this.otherLabels = otherLabels || $('.js-other-labels');
this.errorMessage = 'Unable to update label prioritization at this time';
this.emptyState = document.querySelector('#js-priority-labels-empty-state');
this.sortable = Sortable.create(this.prioritizedLabels.get(0), {
filter: '.empty-message',
forceFallback: true,
fallbackClass: 'is-dragging',
dataIdAttr: 'data-id',
onUpdate: this.onPrioritySortUpdate.bind(this),
});
this.bindEvents();
}
onTogglePriorityClick(e) { bindEvents() {
e.preventDefault(); this.prioritizedLabels.find('.btn-action').on('mousedown', this, this.onButtonActionClick);
const _this = e.data; return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
const $btn = $(e.currentTarget); }
const $label = $(`#${$btn.data('domId')}`);
const action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add';
const $tooltip = $(`#${$btn.find('.has-tooltip:visible').attr('aria-describedby')}`);
$tooltip.tooltip('destroy');
_this.toggleLabelPriority($label, action);
_this.toggleEmptyState($label, $btn, action);
}
onButtonActionClick(e) { onTogglePriorityClick(e) {
e.stopPropagation(); e.preventDefault();
$(e.currentTarget).tooltip('hide'); const _this = e.data;
} const $btn = $(e.currentTarget);
const $label = $(`#${$btn.data('domId')}`);
const action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add';
const $tooltip = $(`#${$btn.find('.has-tooltip:visible').attr('aria-describedby')}`);
$tooltip.tooltip('destroy');
_this.toggleLabelPriority($label, action);
_this.toggleEmptyState($label, $btn, action);
}
toggleEmptyState($label, $btn, action) { onButtonActionClick(e) {
this.emptyState.classList.toggle('hidden', !!this.prioritizedLabels[0].querySelector(':scope > li')); e.stopPropagation();
} $(e.currentTarget).tooltip('hide');
}
toggleLabelPriority($label, action, persistState) { toggleEmptyState($label, $btn, action) {
if (persistState == null) { this.emptyState.classList.toggle('hidden', !!this.prioritizedLabels[0].querySelector(':scope > li'));
persistState = true; }
}
let xhr;
const _this = this;
const url = $label.find('.js-toggle-priority').data('url');
let $target = this.prioritizedLabels;
let $from = this.otherLabels;
if (action === 'remove') {
$target = this.otherLabels;
$from = this.prioritizedLabels;
}
$label.detach().appendTo($target);
if ($from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
}
if ($target.find('> li:not(.empty-message)').length) {
$target.find('.empty-message').addClass('hidden');
}
// Return if we are not persisting state
if (!persistState) {
return;
}
if (action === 'remove') {
xhr = $.ajax({
url,
type: 'DELETE'
});
// Restore empty message
if (!$from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
}
} else {
xhr = this.savePrioritySort($label, action);
}
return xhr.fail(this.rollbackLabelPosition.bind(this, $label, action));
}
onPrioritySortUpdate() { toggleLabelPriority($label, action, persistState) {
const xhr = this.savePrioritySort(); if (persistState == null) {
return xhr.fail(function() { persistState = true;
return new Flash(this.errorMessage, 'alert');
});
} }
let xhr;
savePrioritySort() { const _this = this;
return $.post({ const url = $label.find('.js-toggle-priority').data('url');
url: this.prioritizedLabels.data('url'), let $target = this.prioritizedLabels;
data: { let $from = this.otherLabels;
label_ids: this.getSortedLabelsIds() if (action === 'remove') {
} $target = this.otherLabels;
$from = this.prioritizedLabels;
}
$label.detach().appendTo($target);
if ($from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
}
if ($target.find('> li:not(.empty-message)').length) {
$target.find('.empty-message').addClass('hidden');
}
// Return if we are not persisting state
if (!persistState) {
return;
}
if (action === 'remove') {
xhr = $.ajax({
url,
type: 'DELETE'
}); });
// Restore empty message
if (!$from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
}
} else {
xhr = this.savePrioritySort($label, action);
} }
return xhr.fail(this.rollbackLabelPosition.bind(this, $label, action));
}
rollbackLabelPosition($label, originalAction) { onPrioritySortUpdate() {
const action = originalAction === 'remove' ? 'add' : 'remove'; const xhr = this.savePrioritySort();
this.toggleLabelPriority($label, action, false); return xhr.fail(function() {
return new Flash(this.errorMessage, 'alert'); return new Flash(this.errorMessage, 'alert');
} });
}
getSortedLabelsIds() { savePrioritySort() {
const sortedIds = []; return $.post({
this.prioritizedLabels.find('> li').each(function() { url: this.prioritizedLabels.data('url'),
const id = $(this).data('id'); data: {
label_ids: this.getSortedLabelsIds()
}
});
}
if (id) { rollbackLabelPosition($label, originalAction) {
sortedIds.push(id); const action = originalAction === 'remove' ? 'add' : 'remove';
} this.toggleLabelPriority($label, action, false);
}); return new Flash(this.errorMessage, 'alert');
return sortedIds;
}
} }
gl.LabelManager = LabelManager; getSortedLabelsIds() {
})(window.gl || (window.gl = {})); const sortedIds = [];
this.prioritizedLabels.find('> li').each(function() {
const id = $(this).data('id');
if (id) {
sortedIds.push(id);
}
});
return sortedIds;
}
}
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, vars-on-top, no-unused-vars, max-len */ export default class Labels {
(function() { constructor() {
this.Labels = (function() { this.setSuggestedColor = this.setSuggestedColor.bind(this);
function Labels() { this.updateColorPreview = this.updateColorPreview.bind(this);
this.setSuggestedColor = this.setSuggestedColor.bind(this); this.cleanBinding();
this.updateColorPreview = this.updateColorPreview.bind(this); this.addBinding();
var form; this.updateColorPreview();
form = $('.label-form'); }
this.cleanBinding();
this.addBinding();
this.updateColorPreview();
}
Labels.prototype.addBinding = function() { addBinding() {
$(document).on('click', '.suggest-colors a', this.setSuggestedColor); $(document).on('click', '.suggest-colors a', this.setSuggestedColor);
return $(document).on('input', 'input#label_color', this.updateColorPreview); return $(document).on('input', 'input#label_color', this.updateColorPreview);
}; }
// eslint-disable-next-line class-methods-use-this
cleanBinding() {
$(document).off('click', '.suggest-colors a');
return $(document).off('input', 'input#label_color');
}
// eslint-disable-next-line class-methods-use-this
updateColorPreview() {
const previewColor = $('input#label_color').val();
return $('div.label-color-preview').css('background-color', previewColor);
// Updates the the preview color with the hex-color input
}
Labels.prototype.cleanBinding = function() { // Updates the preview color with a click on a suggested color
$(document).off('click', '.suggest-colors a'); setSuggestedColor(e) {
return $(document).off('input', 'input#label_color'); const color = $(e.currentTarget).data('color');
}; $('input#label_color').val(color);
this.updateColorPreview();
Labels.prototype.updateColorPreview = function() { // Notify the form, that color has changed
var previewColor; $('.label-form').trigger('keyup');
previewColor = $('input#label_color').val(); return e.preventDefault();
return $('div.label-color-preview').css('background-color', previewColor); }
// Updates the the preview color with the hex-color input }
};
// Updates the preview color with a click on a suggested color
Labels.prototype.setSuggestedColor = function(e) {
var color;
color = $(e.currentTarget).data('color');
$('input#label_color').val(color);
this.updateColorPreview();
// Notify the form, that color has changed
$('.label-form').trigger('keyup');
return e.preventDefault();
};
return Labels;
})();
}).call(window);
...@@ -285,7 +285,7 @@ import CreateLabelDropdown from './create_label'; ...@@ -285,7 +285,7 @@ import CreateLabelDropdown from './create_label';
}, },
hidden: function() { hidden: function() {
var isIssueIndex, isMRIndex, page, selectedLabels; var isIssueIndex, isMRIndex, page, selectedLabels;
page = $('body').data('page'); page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index'; isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index'; isMRIndex = page === 'projects:merge_requests:index';
$selectbox.hide(); $selectbox.hide();
...@@ -325,7 +325,7 @@ import CreateLabelDropdown from './create_label'; ...@@ -325,7 +325,7 @@ import CreateLabelDropdown from './create_label';
$loading.fadeOut(); $loading.fadeOut();
}; };
page = $('body').data('page'); page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index'; isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index'; isMRIndex = page === 'projects:merge_requests:index';
......
export const getPagePath = (index = 0) => $('body').data('page').split(':')[index]; export const getPagePath = (index = 0) => $('body').attr('data-page').split(':')[index];
export const isInGroupsPage = () => getPagePath() === 'groups'; export const isInGroupsPage = () => getPagePath() === 'groups';
......
/* eslint-disable 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 */ /* 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'; import 'vendor/latinise';
...@@ -13,9 +13,17 @@ if ((base = w.gl).text == null) { ...@@ -13,9 +13,17 @@ if ((base = w.gl).text == null) {
gl.text.addDelimiter = function(text) { gl.text.addDelimiter = function(text) {
return text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : text; return text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : text;
}; };
gl.text.highCountTrim = function(count) {
/**
* Returns '99+' for numbers bigger than 99.
*
* @param {Number} count
* @return {Number|String}
*/
export function highCountTrim(count) {
return count > 99 ? '99+' : count; return count > 99 ? '99+' : count;
}; }
gl.text.randomString = function() { gl.text.randomString = function() {
return Math.random().toString(36).substring(7); return Math.random().toString(36).substring(7);
}; };
......
/* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len, no-multi-spaces, import/newline-after-import, import/first */ /* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len, no-multi-spaces, import/newline-after-import, import/first */
/* global Flash */
/* global ConfirmDangerModal */ /* global ConfirmDangerModal */
/* global Aside */ /* global Aside */
...@@ -47,25 +46,14 @@ import './lib/utils/url_utility'; ...@@ -47,25 +46,14 @@ import './lib/utils/url_utility';
// behaviors // behaviors
import './behaviors/'; import './behaviors/';
// u2f
import './u2f/authenticate';
import './u2f/error';
import './u2f/register';
import './u2f/util';
// everything else // everything else
import './activities'; import './activities';
import './admin'; import './admin';
import './api';
import './aside'; import './aside';
import './autosave'; import './autosave';
import loadAwardsHandler from './awards_handler'; import loadAwardsHandler from './awards_handler';
import bp from './breakpoints'; import bp from './breakpoints';
import './broadcast_message'; import './broadcast_message';
import './build';
import './build_artifacts';
import './build_variables';
import './ci_lint_editor';
import './commits'; import './commits';
import './compare'; import './compare';
import './compare_autocomplete'; import './compare_autocomplete';
...@@ -76,7 +64,7 @@ import './diff'; ...@@ -76,7 +64,7 @@ import './diff';
import './dropzone_input'; import './dropzone_input';
import './due_date_select'; import './due_date_select';
import './files_comment_button'; import './files_comment_button';
import './flash'; import Flash from './flash';
import './gl_dropdown'; import './gl_dropdown';
import './gl_field_error'; import './gl_field_error';
import './gl_field_errors'; import './gl_field_errors';
...@@ -91,8 +79,6 @@ import './issuable_context'; ...@@ -91,8 +79,6 @@ import './issuable_context';
import './issuable_form'; import './issuable_form';
import './issue'; import './issue';
import './issue_status_select'; import './issue_status_select';
import './label_manager';
import './labels';
import './labels_select'; import './labels_select';
import './layout_nav'; import './layout_nav';
import LazyLoader from './lazy_loader'; import LazyLoader from './lazy_loader';
...@@ -130,7 +116,6 @@ import './right_sidebar'; ...@@ -130,7 +116,6 @@ import './right_sidebar';
import './search'; import './search';
import './search_autocomplete'; import './search_autocomplete';
import './smart_interval'; import './smart_interval';
import './star';
import './subscription'; import './subscription';
import './subscription_select'; import './subscription_select';
import initBreadcrumbs from './breadcrumb'; import initBreadcrumbs from './breadcrumb';
...@@ -169,7 +154,6 @@ $(function () { ...@@ -169,7 +154,6 @@ $(function () {
var $document = $(document); var $document = $(document);
var $window = $(window); var $window = $(window);
var $sidebarGutterToggle = $('.js-sidebar-toggle'); var $sidebarGutterToggle = $('.js-sidebar-toggle');
var $flash = $('.flash-container');
var bootstrapBreakpoint = bp.getBreakpointSize(); var bootstrapBreakpoint = bp.getBreakpointSize();
var fitSidebarForSize; var fitSidebarForSize;
...@@ -254,13 +238,6 @@ $(function () { ...@@ -254,13 +238,6 @@ $(function () {
// Form submitter // Form submitter
}); });
gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), true); gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), true);
// Flash
if ($flash.length > 0) {
$flash.click(function () {
return $(this).fadeOut();
});
$flash.show();
}
// Disable form buttons while a form is submitting // Disable form buttons while a form is submitting
$body.on('ajax:complete, ajax:beforeSend, submit', 'form', function (e) { $body.on('ajax:complete, ajax:beforeSend, submit', 'form', function (e) {
var buttons; var buttons;
......
/* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, no-new, no-param-reassign, max-len */ /* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, no-new, no-param-reassign, max-len */
/* global ace */ /* global ace */
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../../flash';
((global) => { ((global) => {
global.mergeConflicts = global.mergeConflicts || {}; global.mergeConflicts = global.mergeConflicts || {};
......
/* eslint-disable new-cap, comma-dangle, no-new */ /* eslint-disable new-cap, comma-dangle, no-new */
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../flash';
import initIssuableSidebar from '../init_issuable_sidebar'; import initIssuableSidebar from '../init_issuable_sidebar';
import './merge_conflict_store'; import './merge_conflict_store';
import './merge_conflict_service'; import './merge_conflict_service';
......
/* eslint-disable no-new, class-methods-use-this */ /* eslint-disable no-new, class-methods-use-this */
/* global Flash */
/* global notes */ /* global notes */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import './flash'; import Flash from './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';
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-use-before-define, camelcase, quotes, object-shorthand, no-shadow, no-unused-vars, comma-dangle, no-var, prefer-template, no-underscore-dangle, consistent-return, one-var, one-var-declaration-per-line, default-case, prefer-arrow-callback, max-len */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-use-before-define, camelcase, quotes, object-shorthand, no-shadow, no-unused-vars, comma-dangle, no-var, prefer-template, no-underscore-dangle, consistent-return, one-var, one-var-declaration-per-line, default-case, prefer-arrow-callback, max-len */
/* global Flash */
/* global Sortable */ /* global Sortable */
import Flash from './flash';
(function() { (function() {
this.Milestone = (function() { this.Milestone = (function() {
function Milestone() { function Milestone() {
......
...@@ -147,7 +147,7 @@ import _ from 'underscore'; ...@@ -147,7 +147,7 @@ import _ from 'underscore';
const { $el, e } = options; const { $el, e } = options;
let selected = options.selectedObj; let selected = options.selectedObj;
var data, isIssueIndex, isMRIndex, isSelecting, page, boardsStore; var data, isIssueIndex, isMRIndex, isSelecting, page, boardsStore;
page = $('body').data('page'); page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index'; isIssueIndex = page === 'projects:issues:index';
isMRIndex = (page === page && page === 'projects:merge_requests:index'); isMRIndex = (page === page && page === 'projects:merge_requests:index');
isSelecting = (selected.name !== selectedMilestone); isSelecting = (selected.name !== selectedMilestone);
......
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Flash */ import Flash from './flash';
/** /**
* In each pipelines table we have a mini pipeline graph for each pipeline. * In each pipelines table we have a mini pipeline graph for each pipeline.
......
<script> <script>
/* global Flash */
import _ from 'underscore'; import _ from 'underscore';
import Flash from '../../flash';
import MonitoringService from '../services/monitoring_service'; import MonitoringService from '../services/monitoring_service';
import GraphGroup from './graph_group.vue'; import GraphGroup from './graph_group.vue';
import Graph from './graph.vue'; import Graph from './graph.vue';
......
...@@ -5,7 +5,6 @@ default-case, prefer-template, consistent-return, no-alert, no-return-assign, ...@@ -5,7 +5,6 @@ default-case, prefer-template, consistent-return, no-alert, no-return-assign,
no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new, no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new,
brace-style, no-lonely-if, vars-on-top, no-unused-vars, no-sequences, no-shadow, brace-style, no-lonely-if, vars-on-top, no-unused-vars, no-sequences, no-shadow,
newline-per-chained-call, no-useless-escape, class-methods-use-this */ newline-per-chained-call, no-useless-escape, class-methods-use-this */
/* global Flash */
/* global Autosave */ /* global Autosave */
/* global ResolveService */ /* global ResolveService */
/* global mrRefreshWidgetUrl */ /* global mrRefreshWidgetUrl */
...@@ -18,7 +17,9 @@ import Dropzone from 'dropzone'; ...@@ -18,7 +17,9 @@ import Dropzone from 'dropzone';
import 'vendor/jquery.caret'; // required by jquery.atwho import 'vendor/jquery.caret'; // required by jquery.atwho
import 'vendor/jquery.atwho'; import 'vendor/jquery.atwho';
import AjaxCache from '~/lib/utils/ajax_cache'; import AjaxCache from '~/lib/utils/ajax_cache';
import Flash from './flash';
import CommentTypeToggle from './comment_type_toggle'; import CommentTypeToggle from './comment_type_toggle';
import GLForm from './gl_form';
import loadAwardsHandler from './awards_handler'; import loadAwardsHandler from './awards_handler';
import './autosave'; import './autosave';
import './dropzone_input'; import './dropzone_input';
...@@ -354,7 +355,7 @@ export default class Notes { ...@@ -354,7 +355,7 @@ export default class Notes {
Object.keys(noteEntity.commands_changes).length > 0) { Object.keys(noteEntity.commands_changes).length > 0) {
$notesList.find('.system-note.being-posted').remove(); $notesList.find('.system-note.being-posted').remove();
} }
this.addFlash(noteEntity.errors.commands_only, 'notice', this.parentTimeline); this.addFlash(noteEntity.errors.commands_only, 'notice', this.parentTimeline.get(0));
this.refresh(); this.refresh();
} }
return; return;
...@@ -557,7 +558,7 @@ export default class Notes { ...@@ -557,7 +558,7 @@ export default class Notes {
*/ */
setupNoteForm(form) { setupNoteForm(form) {
var textarea, key; var textarea, key;
new gl.GLForm(form, this.enableGFM); this.glForm = new GLForm(form, this.enableGFM);
textarea = form.find('.js-note-text'); textarea = form.find('.js-note-text');
key = [ key = [
'Note', 'Note',
...@@ -593,7 +594,7 @@ export default class Notes { ...@@ -593,7 +594,7 @@ export default class Notes {
} else if ($form.hasClass('js-discussion-note-form')) { } else if ($form.hasClass('js-discussion-note-form')) {
formParentTimeline = $form.closest('.discussion-notes').find('.notes'); formParentTimeline = $form.closest('.discussion-notes').find('.notes');
} }
return this.addFlash('Your comment could not be submitted! Please check your network connection and try again.', 'alert', formParentTimeline); return this.addFlash('Your comment could not be submitted! Please check your network connection and try again.', 'alert', formParentTimeline.get(0));
} }
updateNoteError($parentTimeline) { updateNoteError($parentTimeline) {
...@@ -1152,7 +1153,7 @@ export default class Notes { ...@@ -1152,7 +1153,7 @@ export default class Notes {
var targetId = $originalContentEl.data('target-id'); var targetId = $originalContentEl.data('target-id');
var targetType = $originalContentEl.data('target-type'); var targetType = $originalContentEl.data('target-type');
new gl.GLForm($editForm.find('form'), this.enableGFM); this.glForm = new GLForm($editForm.find('form'), this.enableGFM);
$editForm.find('form') $editForm.find('form')
.attr('action', postUrl) .attr('action', postUrl)
...@@ -1213,13 +1214,13 @@ export default class Notes { ...@@ -1213,13 +1214,13 @@ export default class Notes {
} }
addFlash(...flashParams) { addFlash(...flashParams) {
this.flashInstance = new Flash(...flashParams); this.flashContainer = new Flash(...flashParams);
} }
clearFlash() { clearFlash() {
if (this.flashInstance && this.flashInstance.flashContainer) { if (this.flashContainer) {
this.flashInstance.flashContainer.hide(); this.flashContainer.style.display = 'none';
this.flashInstance = null; this.flashContainer = null;
} }
} }
...@@ -1257,7 +1258,7 @@ export default class Notes { ...@@ -1257,7 +1258,7 @@ export default class Notes {
} }
static checkMergeRequestStatus() { static checkMergeRequestStatus() {
if (getPagePath(1) === 'merge_requests') { if (getPagePath(1) === 'merge_requests' && gl.mrWidget) {
gl.mrWidget.checkStatus(); gl.mrWidget.checkStatus();
} }
} }
......
<script> <script>
/* global Flash, Autosave */ /* global Autosave */
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import _ from 'underscore'; import _ from 'underscore';
import autosize from 'vendor/autosize'; import autosize from 'vendor/autosize';
import Flash from '../../flash';
import '../../autosave'; import '../../autosave';
import TaskList from '../../task_list'; import TaskList from '../../task_list';
import * as constants from '../constants'; import * as constants from '../constants';
...@@ -145,7 +146,7 @@ ...@@ -145,7 +146,7 @@
Flash( Flash(
'Something went wrong while adding your comment. Please try again.', 'Something went wrong while adding your comment. Please try again.',
'alert', 'alert',
$(this.$refs.commentForm), this.$refs.commentForm,
); );
} }
} else { } else {
...@@ -160,7 +161,7 @@ ...@@ -160,7 +161,7 @@
this.isSubmitting = false; this.isSubmitting = false;
this.discard(false); this.discard(false);
const msg = 'Your comment could not be submitted! Please check your network connection and try again.'; const msg = 'Your comment could not be submitted! Please check your network connection and try again.';
Flash(msg, 'alert', $(this.$el)); Flash(msg, 'alert', this.$el);
this.note = noteData.data.note.note; // Restore textarea content. this.note = noteData.data.note.note; // Restore textarea content.
this.removePlaceholderNotes(); this.removePlaceholderNotes();
}); });
......
<script> <script>
/* global Flash */
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import Flash from '../../flash';
import { SYSTEM_NOTE } from '../constants'; import { SYSTEM_NOTE } from '../constants';
import issueNote from './issue_note.vue'; import issueNote from './issue_note.vue';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
this.isReplying = true; this.isReplying = true;
this.$nextTick(() => { this.$nextTick(() => {
const msg = 'Your comment could not be submitted! Please check your network connection and try again.'; const msg = 'Your comment could not be submitted! Please check your network connection and try again.';
Flash(msg, 'alert', $(this.$el)); Flash(msg, 'alert', this.$el);
this.$refs.noteForm.note = noteText; this.$refs.noteForm.note = noteText;
callback(err); callback(err);
}); });
......
<script> <script>
/* global Flash */
import { mapGetters, mapActions } from 'vuex'; import { mapGetters, mapActions } from 'vuex';
import Flash from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import issueNoteHeader from './issue_note_header.vue'; import issueNoteHeader from './issue_note_header.vue';
import issueNoteActions from './issue_note_actions.vue'; import issueNoteActions from './issue_note_actions.vue';
...@@ -101,7 +100,7 @@ ...@@ -101,7 +100,7 @@
this.isEditing = true; this.isEditing = true;
this.$nextTick(() => { this.$nextTick(() => {
const msg = 'Something went wrong while editing your comment. Please try again.'; const msg = 'Something went wrong while editing your comment. Please try again.';
Flash(msg, 'alert', $(this.$el)); Flash(msg, 'alert', this.$el);
this.recoverNoteContent(noteText); this.recoverNoteContent(noteText);
callback(); callback();
}); });
......
<script> <script>
/* global Flash */
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg'; import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
import emojiSmile from 'icons/_emoji_smile.svg'; import emojiSmile from 'icons/_emoji_smile.svg';
import emojiSmiley from 'icons/_emoji_smiley.svg'; import emojiSmiley from 'icons/_emoji_smiley.svg';
import Flash from '../../flash';
import { glEmojiTag } from '../../emoji'; import { glEmojiTag } from '../../emoji';
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
......
<script> <script>
/* global Flash */
import { mapGetters, mapActions } from 'vuex'; import { mapGetters, mapActions } from 'vuex';
import Flash from '../../flash';
import store from '../stores/'; import store from '../stores/';
import * as constants from '../constants'; import * as constants from '../constants';
import issueNote from './issue_note.vue'; import issueNote from './issue_note.vue';
......
/* global Flash */
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll'; import Poll from '../../lib/utils/poll';
import * as types from './mutation_types'; import * as types from './mutation_types';
import * as utils from './utils'; import * as utils from './utils';
...@@ -99,7 +99,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => { ...@@ -99,7 +99,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
eTagPoll.makeRequest(); eTagPoll.makeRequest();
$('.js-gfm-input').trigger('clear-commands-cache.atwho'); $('.js-gfm-input').trigger('clear-commands-cache.atwho');
Flash('Commands applied', 'notice', $(noteData.flashContainer)); Flash('Commands applied', 'notice', noteData.flashContainer);
} }
if (commandsChanges) { if (commandsChanges) {
...@@ -114,8 +114,8 @@ export const saveNote = ({ commit, dispatch }, noteData) => { ...@@ -114,8 +114,8 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
.catch(() => { .catch(() => {
Flash( Flash(
'Something went wrong while adding your award. Please try again.', 'Something went wrong while adding your award. Please try again.',
null, 'alert',
$(noteData.flashContainer), noteData.flashContainer,
); );
}); });
} }
...@@ -126,7 +126,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => { ...@@ -126,7 +126,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
} }
if (errors && errors.commands_only) { if (errors && errors.commands_only) {
Flash(errors.commands_only, 'notice', $(noteData.flashContainer)); Flash(errors.commands_only, 'notice', noteData.flashContainer);
} }
commit(types.REMOVE_PLACEHOLDER_NOTES); commit(types.REMOVE_PLACEHOLDER_NOTES);
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, consistent-return, prefer-arrow-callback, no-else-return, max-len */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, consistent-return, prefer-arrow-callback, no-else-return, max-len */
/* global Flash */ import Flash from './flash';
(function() { (function() {
this.NotificationsDropdown = (function() { this.NotificationsDropdown = (function() {
......
import Vue from 'vue'; import Vue from 'vue';
import Translate from '../vue_shared/translate'; import Translate from '../vue_shared/translate';
import GlFieldErrors from '../gl_field_errors';
import intervalPatternInput from './components/interval_pattern_input.vue'; import intervalPatternInput from './components/interval_pattern_input.vue';
import TimezoneDropdown from './components/timezone_dropdown'; import TimezoneDropdown from './components/timezone_dropdown';
import TargetBranchDropdown from './components/target_branch_dropdown'; import TargetBranchDropdown from './components/target_branch_dropdown';
...@@ -39,7 +40,7 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -39,7 +40,7 @@ document.addEventListener('DOMContentLoaded', () => {
gl.timezoneDropdown = new TimezoneDropdown(); gl.timezoneDropdown = new TimezoneDropdown();
gl.targetBranchDropdown = new TargetBranchDropdown(); gl.targetBranchDropdown = new TargetBranchDropdown();
gl.pipelineScheduleFieldErrors = new gl.GlFieldErrors(formElement); gl.pipelineScheduleFieldErrors = new GlFieldErrors(formElement);
setupPipelineVariableList($('.js-pipeline-variable-list')); setupPipelineVariableList($('.js-pipeline-variable-list'));
}); });
<script> <script>
/* global Flash */
import '~/flash';
import playIconSvg from 'icons/_icon_play.svg'; import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue'; import loadingIcon from '../../vue_shared/components/loading_icon.vue';
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* 4. Commit widget * 4. Commit widget
*/ */
/* global Flash */ import Flash from '../../flash';
import { borderlessStatusIconEntityMap } from '../../vue_shared/ci_status_icons'; import { borderlessStatusIconEntityMap } from '../../vue_shared/ci_status_icons';
import loadingIcon from '../../vue_shared/components/loading_icon.vue'; import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tooltip from '../../vue_shared/directives/tooltip'; import tooltip from '../../vue_shared/directives/tooltip';
......
/* global Flash */
import '~/flash';
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll'; import Poll from '../../lib/utils/poll';
import emptyState from '../components/empty_state.vue'; import emptyState from '../components/empty_state.vue';
import errorState from '../components/error_state.vue'; import errorState from '../components/error_state.vue';
......
/* global Flash */
import Vue from 'vue'; import Vue from 'vue';
import Flash from '../flash';
import PipelinesMediator from './pipeline_details_mediatior'; import PipelinesMediator from './pipeline_details_mediatior';
import pipelineGraph from './components/graph/graph_component.vue'; import pipelineGraph from './components/graph/graph_component.vue';
import pipelineHeader from './components/header_component.vue'; import pipelineHeader from './components/header_component.vue';
......
/* global Flash */
import Visibility from 'visibilityjs'; import Visibility from 'visibilityjs';
import Flash from '../flash';
import Poll from '../lib/utils/poll'; import Poll from '../lib/utils/poll';
import PipelineStore from './stores/pipeline_store'; import PipelineStore from './stores/pipeline_store';
import PipelineService from './services/pipeline_service'; import PipelineService from './services/pipeline_service';
......
/* 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 */ import Flash from '../flash';
import { getPagePath } from '../lib/utils/common_utils'; import { getPagePath } from '../lib/utils/common_utils';
((global) => { ((global) => {
......
...@@ -29,6 +29,12 @@ const bindEvents = () => { ...@@ -29,6 +29,12 @@ const bindEvents = () => {
const $newProjectForm = $('#new_project'); const $newProjectForm = $('#new_project');
const $projectImportUrl = $('#project_import_url'); const $projectImportUrl = $('#project_import_url');
const $projectPath = $('#project_path'); const $projectPath = $('#project_path');
const $useTemplateBtn = $('.template-button > input');
const $projectFieldsForm = $('.project-fields-form');
const $selectedTemplateText = $('.selected-template');
const $changeTemplateBtn = $('.change-template');
const $selectedIcon = $('.selected-icon svg');
const $templateProjectNameInput = $('#template-project-name #project_path');
if ($newProjectForm.length !== 1) { if ($newProjectForm.length !== 1) {
return; return;
...@@ -48,6 +54,40 @@ const bindEvents = () => { ...@@ -48,6 +54,40 @@ const bindEvents = () => {
$('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$projectPath.val()}`); $('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$projectPath.val()}`);
}); });
function chooseTemplate() {
$('.template-option').hide();
$projectFieldsForm.addClass('selected');
$selectedIcon.removeClass('active');
const value = $(this).val();
const templates = {
rails: {
text: 'Ruby on Rails',
icon: '.selected-icon .icon-rails',
},
express: {
text: 'NodeJS Express',
icon: '.selected-icon .icon-node-express',
},
spring: {
text: 'Spring',
icon: '.selected-icon .icon-java-spring',
},
};
const selectedTemplate = templates[value];
$selectedTemplateText.text(selectedTemplate.text);
$(selectedTemplate.icon).addClass('active');
$templateProjectNameInput.focus();
}
$useTemplateBtn.on('change', chooseTemplate);
$changeTemplateBtn.on('click', () => {
$('.template-option').show();
$projectFieldsForm.removeClass('selected');
$useTemplateBtn.prop('checked', false);
});
$newProjectForm.on('submit', () => { $newProjectForm.on('submit', () => {
$projectPath.val($projectPath.val().trim()); $projectPath.val($projectPath.val().trim());
}); });
......
...@@ -81,7 +81,11 @@ export default class PrometheusMetrics { ...@@ -81,7 +81,11 @@ export default class PrometheusMetrics {
loadActiveMetrics() { loadActiveMetrics() {
this.showMonitoringMetricsPanelState(PANEL_STATE.LOADING); this.showMonitoringMetricsPanelState(PANEL_STATE.LOADING);
backOff((next, stop) => { backOff((next, stop) => {
$.getJSON(this.activeMetricsEndpoint) $.ajax({
url: this.activeMetricsEndpoint,
dataType: 'json',
global: false,
})
.done((res) => { .done((res) => {
if (res && res.success) { if (res && res.success) {
stop(res); stop(res);
......
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Flash */ import Flash from '../flash';
import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown'; import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown';
export default class ProtectedBranchEdit { export default class ProtectedBranchEdit {
...@@ -57,7 +56,7 @@ export default class ProtectedBranchEdit { ...@@ -57,7 +56,7 @@ export default class ProtectedBranchEdit {
}, },
}, },
error() { error() {
new Flash('Failed to update branch!', null, $('.js-protected-branches-list')); new Flash('Failed to update branch!', 'alert', document.querySelector('.js-protected-branches-list'));
}, },
}).always(() => { }).always(() => {
this.$allowedToMergeDropdown.enable(); this.$allowedToMergeDropdown.enable();
......
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Flash */ import Flash from '../flash';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown'; import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
export default class ProtectedTagEdit { export default class ProtectedTagEdit {
...@@ -43,7 +42,7 @@ export default class ProtectedTagEdit { ...@@ -43,7 +42,7 @@ export default class ProtectedTagEdit {
}, },
}, },
error() { error() {
new Flash('Failed to update tag!', null, $('.js-protected-tags-list')); new Flash('Failed to update tag!', 'alert', document.querySelector('.js-protected-tags-list'));
}, },
}).always(() => { }).always(() => {
this.$allowedToCreateDropdownButton.enable(); this.$allowedToCreateDropdownButton.enable();
......
<script> <script>
/* global Flash */ import Flash from '../../flash';
import Store from '../stores/repo_store'; import Store from '../stores/repo_store';
import RepoMixin from '../mixins/repo_mixin'; import RepoMixin from '../mixins/repo_mixin';
import Service from '../services/repo_service'; import Service from '../services/repo_service';
......
/* global Flash */
import Service from '../services/repo_service'; import Service from '../services/repo_service';
import Store from '../stores/repo_store'; import Store from '../stores/repo_store';
import '../../flash'; import Flash from '../../flash';
const RepoHelper = { const RepoHelper = {
monacoInstance: null, monacoInstance: null,
......
/* global Flash */
import axios from 'axios'; import axios from 'axios';
import Store from '../stores/repo_store'; import Store from '../stores/repo_store';
import Api from '../../api'; import Api from '../../api';
......
/* global Flash */
import Helper from '../helpers/repo_helper'; import Helper from '../helpers/repo_helper';
import Service from '../services/repo_service'; import Service from '../services/repo_service';
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, object-shorthand, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-else-return, max-len */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, object-shorthand, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-else-return, max-len */
/* global Flash */ import Flash from './flash';
import Api from './api'; import Api from './api';
(function() { (function() {
......
/* global Flash */ import Flash from '../../../flash';
import AssigneeTitle from './assignee_title'; import AssigneeTitle from './assignee_title';
import Assignees from './assignees'; import Assignees from './assignees';
......
<script> <script>
/* global Flash */ import Flash from '../../../flash';
import editForm from './edit_form.vue'; import editForm from './edit_form.vue';
export default { export default {
......
/* global Flash */
function isValidProjectId(id) { function isValidProjectId(id) {
return id > 0; return id > 0;
} }
...@@ -38,7 +36,7 @@ class SidebarMoveIssue { ...@@ -38,7 +36,7 @@ class SidebarMoveIssue {
data: (searchTerm, callback) => { data: (searchTerm, callback) => {
this.mediator.fetchAutocompleteProjects(searchTerm) this.mediator.fetchAutocompleteProjects(searchTerm)
.then(callback) .then(callback)
.catch(() => new Flash('An error occurred while fetching projects autocomplete.')); .catch(() => new window.Flash('An error occurred while fetching projects autocomplete.'));
}, },
renderRow: project => ` renderRow: project => `
<li> <li>
...@@ -73,7 +71,7 @@ class SidebarMoveIssue { ...@@ -73,7 +71,7 @@ class SidebarMoveIssue {
this.mediator.moveIssue() this.mediator.moveIssue()
.catch(() => { .catch(() => {
Flash('An error occurred while moving the issue.'); window.Flash('An error occurred while moving the issue.');
this.$confirmButton this.$confirmButton
.enable() .enable()
.removeClass('is-loading'); .removeClass('is-loading');
......
/* global Flash */ import Flash from '../flash';
import Service from './services/sidebar_service'; import Service from './services/sidebar_service';
import Store from './stores/sidebar_store'; import Store from './stores/sidebar_store';
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-unused-vars, one-var, no-var, one-var-declaration-per-line, prefer-arrow-callback, no-new, max-len */ import Flash from './flash';
/* global Flash */
import { __, s__ } from './locale'; import { __, s__ } from './locale';
export default class Star { export default class Star {
constructor() { constructor() {
$('.project-home-panel .toggle-star').on('ajax:success', function(e, data, status, xhr) { $('.project-home-panel .toggle-star')
var $starIcon, $starSpan, $this, toggleStar; .on('ajax:success', function handleSuccess(e, data) {
$this = $(this); const $this = $(this);
$starSpan = $this.find('span'); const $starSpan = $this.find('span');
$starIcon = $this.find('i'); const $starIcon = $this.find('i');
toggleStar = function(isStarred) {
$this.parent().find('.star-count').text(data.star_count); function toggleStar(isStarred) {
if (isStarred) { $this.parent().find('.star-count').text(data.star_count);
$starSpan.removeClass('starred').text(s__('StarProject|Star')); if (isStarred) {
$starIcon.removeClass('fa-star').addClass('fa-star-o'); $starSpan.removeClass('starred').text(s__('StarProject|Star'));
} else { $starIcon.removeClass('fa-star').addClass('fa-star-o');
$starSpan.addClass('starred').text(__('Unstar')); } else {
$starIcon.removeClass('fa-star-o').addClass('fa-star'); $starSpan.addClass('starred').text(__('Unstar'));
$starIcon.removeClass('fa-star-o').addClass('fa-star');
}
} }
};
toggleStar($starSpan.hasClass('starred')); toggleStar($starSpan.hasClass('starred'));
}).on('ajax:error', function(e, xhr, status, error) { })
new Flash('Star toggle failed. Try again later.', 'alert'); .on('ajax:error', () => {
}); Flash('Star toggle failed. Try again later.', 'alert');
});
} }
} }
/* global Flash */
import 'deckar01-task_list'; import 'deckar01-task_list';
import Flash from './flash';
export default class TaskList { export default class TaskList {
constructor(options = {}) { constructor(options = {}) {
......
/* global U2FRegister */ import U2FRegister from './u2f/register';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const twoFactorNode = document.querySelector('.js-two-factor-auth'); const twoFactorNode = document.querySelector('.js-two-factor-auth');
const skippable = twoFactorNode.dataset.twoFactorSkippable === 'true'; const skippable = twoFactorNode.dataset.twoFactorSkippable === 'true';
......
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, prefer-arrow-callback, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, max-len */ /* eslint-disable func-names, wrap-iife */
/* global u2f */ /* global u2f */
/* global U2FError */
/* global U2FUtil */
import _ from 'underscore'; import _ from 'underscore';
import isU2FSupported from './util';
import U2FError from './error';
// Authenticate U2F (universal 2nd factor) devices for users to authenticate with. // Authenticate U2F (universal 2nd factor) devices for users to authenticate with.
// //
// State Flow #1: setup -> in_progress -> authenticated -> POST to server // State Flow #1: setup -> in_progress -> authenticated -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup // State Flow #2: setup -> in_progress -> error -> setup
(function() { export default class U2FAuthenticate {
const global = window.gl || (window.gl = {}); constructor(container, form, u2fParams, fallbackButton, fallbackUI) {
this.container = container;
global.U2FAuthenticate = (function() { this.renderNotSupported = this.renderNotSupported.bind(this);
function U2FAuthenticate(container, form, u2fParams, fallbackButton, fallbackUI) { this.renderAuthenticated = this.renderAuthenticated.bind(this);
this.container = container; this.renderError = this.renderError.bind(this);
this.renderNotSupported = this.renderNotSupported.bind(this); this.renderInProgress = this.renderInProgress.bind(this);
this.renderAuthenticated = this.renderAuthenticated.bind(this); this.renderTemplate = this.renderTemplate.bind(this);
this.renderError = this.renderError.bind(this); this.authenticate = this.authenticate.bind(this);
this.renderInProgress = this.renderInProgress.bind(this); this.start = this.start.bind(this);
this.renderTemplate = this.renderTemplate.bind(this); this.appId = u2fParams.app_id;
this.authenticate = this.authenticate.bind(this); this.challenge = u2fParams.challenge;
this.start = this.start.bind(this); this.form = form;
this.appId = u2fParams.app_id; this.fallbackButton = fallbackButton;
this.challenge = u2fParams.challenge; this.fallbackUI = fallbackUI;
this.form = form; if (this.fallbackButton) {
this.fallbackButton = fallbackButton; this.fallbackButton.addEventListener('click', this.switchToFallbackUI.bind(this));
this.fallbackUI = fallbackUI;
if (this.fallbackButton) this.fallbackButton.addEventListener('click', this.switchToFallbackUI.bind(this));
this.signRequests = u2fParams.sign_requests.map(function(request) {
// The U2F Javascript API v1.1 requires a single challenge, with
// _no challenges per-request_. The U2F Javascript API v1.0 requires a
// challenge per-request, which is done by copying the single challenge
// into every request.
//
// In either case, we don't need the per-request challenges that the server
// has generated, so we can remove them.
//
// Note: The server library fixes this behaviour in (unreleased) version 1.0.0.
// This can be removed once we upgrade.
// https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4
return _(request).omit('challenge');
});
} }
U2FAuthenticate.prototype.start = function() { // The U2F Javascript API v1.1 requires a single challenge, with
if (U2FUtil.isU2FSupported()) { // _no challenges per-request_. The U2F Javascript API v1.0 requires a
return this.renderInProgress(); // challenge per-request, which is done by copying the single challenge
} else { // into every request.
return this.renderNotSupported(); //
} // In either case, we don't need the per-request challenges that the server
}; // has generated, so we can remove them.
//
// Note: The server library fixes this behaviour in (unreleased) version 1.0.0.
// This can be removed once we upgrade.
// https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4
this.signRequests = u2fParams.sign_requests.map(request => _(request).omit('challenge'));
U2FAuthenticate.prototype.authenticate = function() { this.templates = {
return u2f.sign(this.appId, this.challenge, this.signRequests, (function(_this) { notSupported: '#js-authenticate-u2f-not-supported',
return function(response) { setup: '#js-authenticate-u2f-setup',
var error; inProgress: '#js-authenticate-u2f-in-progress',
if (response.errorCode) { error: '#js-authenticate-u2f-error',
error = new U2FError(response.errorCode, 'authenticate'); authenticated: '#js-authenticate-u2f-authenticated',
return _this.renderError(error);
} else {
return _this.renderAuthenticated(JSON.stringify(response));
}
};
})(this), 10);
}; };
}
// Rendering # start() {
U2FAuthenticate.prototype.templates = { if (isU2FSupported()) {
"notSupported": "#js-authenticate-u2f-not-supported", return this.renderInProgress();
"setup": '#js-authenticate-u2f-setup', }
"inProgress": '#js-authenticate-u2f-in-progress', return this.renderNotSupported();
"error": '#js-authenticate-u2f-error', }
"authenticated": '#js-authenticate-u2f-authenticated'
};
U2FAuthenticate.prototype.renderTemplate = function(name, params) { authenticate() {
var template, templateString; return u2f.sign(this.appId, this.challenge, this.signRequests, (function (_this) {
templateString = $(this.templates[name]).html(); return function (response) {
template = _.template(templateString); if (response.errorCode) {
return this.container.html(template(params)); const error = new U2FError(response.errorCode, 'authenticate');
}; return _this.renderError(error);
}
return _this.renderAuthenticated(JSON.stringify(response));
};
})(this), 10);
}
U2FAuthenticate.prototype.renderInProgress = function() { renderTemplate(name, params) {
this.renderTemplate('inProgress'); const templateString = $(this.templates[name]).html();
return this.authenticate(); const template = _.template(templateString);
}; return this.container.html(template(params));
}
U2FAuthenticate.prototype.renderError = function(error) { renderInProgress() {
this.renderTemplate('error', { this.renderTemplate('inProgress');
error_message: error.message(), return this.authenticate();
error_code: error.errorCode }
});
return this.container.find('#js-u2f-try-again').on('click', this.renderInProgress);
};
U2FAuthenticate.prototype.renderAuthenticated = function(deviceResponse) { renderError(error) {
this.renderTemplate('authenticated'); this.renderTemplate('error', {
const container = this.container[0]; error_message: error.message(),
container.querySelector('#js-device-response').value = deviceResponse; error_code: error.errorCode,
container.querySelector(this.form).submit(); });
this.fallbackButton.classList.add('hidden'); return this.container.find('#js-u2f-try-again').on('click', this.renderInProgress);
}; }
U2FAuthenticate.prototype.renderNotSupported = function() { renderAuthenticated(deviceResponse) {
return this.renderTemplate('notSupported'); this.renderTemplate('authenticated');
}; const container = this.container[0];
container.querySelector('#js-device-response').value = deviceResponse;
container.querySelector(this.form).submit();
this.fallbackButton.classList.add('hidden');
}
U2FAuthenticate.prototype.switchToFallbackUI = function() { renderNotSupported() {
this.fallbackButton.classList.add('hidden'); return this.renderTemplate('notSupported');
this.container[0].classList.add('hidden'); }
this.fallbackUI.classList.remove('hidden');
}; switchToFallbackUI() {
this.fallbackButton.classList.add('hidden');
this.container[0].classList.add('hidden');
this.fallbackUI.classList.remove('hidden');
}
return U2FAuthenticate; }
})();
})();
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-console, quotes, prefer-template, max-len */ export default class U2FError {
/* global u2f */ constructor(errorCode, u2fFlowType) {
this.errorCode = errorCode;
this.message = this.message.bind(this);
this.httpsDisabled = window.location.protocol !== 'https:';
this.u2fFlowType = u2fFlowType;
}
(function() { message() {
this.U2FError = (function() { if (this.errorCode === window.u2f.ErrorCodes.BAD_REQUEST && this.httpsDisabled) {
function U2FError(errorCode, u2fFlowType) { return 'U2F only works with HTTPS-enabled websites. Contact your administrator for more details.';
this.errorCode = errorCode; } else if (this.errorCode === window.u2f.ErrorCodes.DEVICE_INELIGIBLE) {
this.message = this.message.bind(this); if (this.u2fFlowType === 'authenticate') {
this.httpsDisabled = window.location.protocol !== 'https:'; return 'This device has not been registered with us.';
this.u2fFlowType = u2fFlowType;
}
U2FError.prototype.message = function() {
if (this.errorCode === u2f.ErrorCodes.BAD_REQUEST && this.httpsDisabled) {
return 'U2F only works with HTTPS-enabled websites. Contact your administrator for more details.';
} else if (this.errorCode === u2f.ErrorCodes.DEVICE_INELIGIBLE) {
if (this.u2fFlowType === 'authenticate') return 'This device has not been registered with us.';
if (this.u2fFlowType === 'register') return 'This device has already been registered with us.';
} }
return "There was a problem communicating with your device."; if (this.u2fFlowType === 'register') {
}; return 'This device has already been registered with us.';
}
return U2FError; }
})(); return 'There was a problem communicating with your device.';
}).call(window); }
}
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-else-return, quotes, quote-props, comma-dangle, one-var, one-var-declaration-per-line, max-len */ /* eslint-disable func-names, wrap-iife */
/* global u2f */ /* global u2f */
/* global U2FError */
/* global U2FUtil */
import _ from 'underscore'; import _ from 'underscore';
import isU2FSupported from './util';
import U2FError from './error';
// Register U2F (universal 2nd factor) devices for users to authenticate with. // Register U2F (universal 2nd factor) devices for users to authenticate with.
// //
// State Flow #1: setup -> in_progress -> registered -> POST to server // State Flow #1: setup -> in_progress -> registered -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup // State Flow #2: setup -> in_progress -> error -> setup
(function() { export default class U2FRegister {
this.U2FRegister = (function() { constructor(container, u2fParams) {
function U2FRegister(container, u2fParams) { this.container = container;
this.container = container; this.renderNotSupported = this.renderNotSupported.bind(this);
this.renderNotSupported = this.renderNotSupported.bind(this); this.renderRegistered = this.renderRegistered.bind(this);
this.renderRegistered = this.renderRegistered.bind(this); this.renderError = this.renderError.bind(this);
this.renderError = this.renderError.bind(this); this.renderInProgress = this.renderInProgress.bind(this);
this.renderInProgress = this.renderInProgress.bind(this); this.renderSetup = this.renderSetup.bind(this);
this.renderSetup = this.renderSetup.bind(this); this.renderTemplate = this.renderTemplate.bind(this);
this.renderTemplate = this.renderTemplate.bind(this); this.register = this.register.bind(this);
this.register = this.register.bind(this); this.start = this.start.bind(this);
this.start = this.start.bind(this); this.appId = u2fParams.app_id;
this.appId = u2fParams.app_id; this.registerRequests = u2fParams.register_requests;
this.registerRequests = u2fParams.register_requests; this.signRequests = u2fParams.sign_requests;
this.signRequests = u2fParams.sign_requests;
}
U2FRegister.prototype.start = function() { this.templates = {
if (U2FUtil.isU2FSupported()) { notSupported: '#js-register-u2f-not-supported',
return this.renderSetup(); setup: '#js-register-u2f-setup',
} else { inProgress: '#js-register-u2f-in-progress',
return this.renderNotSupported(); error: '#js-register-u2f-error',
} registered: '#js-register-u2f-registered',
}; };
}
U2FRegister.prototype.register = function() { start() {
return u2f.register(this.appId, this.registerRequests, this.signRequests, (function(_this) { if (isU2FSupported()) {
return function(response) { return this.renderSetup();
var error; }
if (response.errorCode) { return this.renderNotSupported();
error = new U2FError(response.errorCode, 'register'); }
return _this.renderError(error);
} else {
return _this.renderRegistered(JSON.stringify(response));
}
};
})(this), 10);
};
// Rendering # register() {
U2FRegister.prototype.templates = { return u2f.register(this.appId, this.registerRequests, this.signRequests, (function (_this) {
"notSupported": "#js-register-u2f-not-supported", return function (response) {
"setup": '#js-register-u2f-setup', if (response.errorCode) {
"inProgress": '#js-register-u2f-in-progress', const error = new U2FError(response.errorCode, 'register');
"error": '#js-register-u2f-error', return _this.renderError(error);
"registered": '#js-register-u2f-registered' }
}; return _this.renderRegistered(JSON.stringify(response));
};
})(this), 10);
}
U2FRegister.prototype.renderTemplate = function(name, params) { renderTemplate(name, params) {
var template, templateString; const templateString = $(this.templates[name]).html();
templateString = $(this.templates[name]).html(); const template = _.template(templateString);
template = _.template(templateString); return this.container.html(template(params));
return this.container.html(template(params)); }
};
U2FRegister.prototype.renderSetup = function() { renderSetup() {
this.renderTemplate('setup'); this.renderTemplate('setup');
return this.container.find('#js-setup-u2f-device').on('click', this.renderInProgress); return this.container.find('#js-setup-u2f-device').on('click', this.renderInProgress);
}; }
U2FRegister.prototype.renderInProgress = function() { renderInProgress() {
this.renderTemplate('inProgress'); this.renderTemplate('inProgress');
return this.register(); return this.register();
}; }
U2FRegister.prototype.renderError = function(error) { renderError(error) {
this.renderTemplate('error', { this.renderTemplate('error', {
error_message: error.message(), error_message: error.message(),
error_code: error.errorCode error_code: error.errorCode,
}); });
return this.container.find('#js-u2f-try-again').on('click', this.renderSetup); return this.container.find('#js-u2f-try-again').on('click', this.renderSetup);
}; }
U2FRegister.prototype.renderRegistered = function(deviceResponse) { renderRegistered(deviceResponse) {
this.renderTemplate('registered'); this.renderTemplate('registered');
// Prefer to do this instead of interpolating using Underscore templates // Prefer to do this instead of interpolating using Underscore templates
// because of JSON escaping issues. // because of JSON escaping issues.
return this.container.find("#js-device-response").val(deviceResponse); return this.container.find('#js-device-response').val(deviceResponse);
}; }
U2FRegister.prototype.renderNotSupported = function() {
return this.renderTemplate('notSupported');
};
return U2FRegister; renderNotSupported() {
})(); return this.renderTemplate('notSupported');
}).call(window); }
}
/* eslint-disable func-names, space-before-function-paren, wrap-iife */ export default function isU2FSupported() {
(function() { return window.u2f;
this.U2FUtil = (function() { }
function U2FUtil() {}
U2FUtil.isU2FSupported = function() {
return window.u2f;
};
return U2FUtil;
})();
}).call(window);
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import UserTabs from './user_tabs'; import UserTabs from './user_tabs';
export default function initUserProfile(action) { function initUserProfile(action) {
// place profile avatars to top // place profile avatars to top
$('.profile-groups-avatars').tooltip({ $('.profile-groups-avatars').tooltip({
placement: 'top', placement: 'top',
...@@ -17,3 +17,9 @@ export default function initUserProfile(action) { ...@@ -17,3 +17,9 @@ export default function initUserProfile(action) {
$(this).parents('.project-limit-message').remove(); $(this).parents('.project-limit-message').remove();
}); });
} }
document.addEventListener('DOMContentLoaded', () => {
const page = $('body').attr('data-page');
const action = page.split(':')[1];
initUserProfile(action);
});
...@@ -424,7 +424,7 @@ function UsersSelect(currentUser, els) { ...@@ -424,7 +424,7 @@ function UsersSelect(currentUser, els) {
} }
var isIssueIndex, isMRIndex, page, selected; var isIssueIndex, isMRIndex, page, selected;
page = $('body').data('page'); page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index'; isIssueIndex = page === 'projects:issues:index';
isMRIndex = (page === page && page === 'projects:merge_requests:index'); isMRIndex = (page === page && page === 'projects:merge_requests:index');
if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) { if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
......
/* global Flash */
import '~/lib/utils/datetime_utility'; import '~/lib/utils/datetime_utility';
import Flash from '../../flash';
import MemoryUsage from './mr_widget_memory_usage'; import MemoryUsage from './mr_widget_memory_usage';
import StatusIcon from './mr_widget_status_icon'; import StatusIcon from './mr_widget_status_icon';
import MRWidgetService from '../services/mr_widget_service'; import MRWidgetService from '../services/mr_widget_service';
......
/* global Flash */ import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon'; import statusIcon from '../mr_widget_status_icon';
import MRWidgetAuthor from '../../components/mr_widget_author'; import MRWidgetAuthor from '../../components/mr_widget_author';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
......
/* global Flash */ import Flash from '../../../flash';
import mrWidgetAuthorTime from '../../components/mr_widget_author_time'; import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
import tooltip from '../../../vue_shared/directives/tooltip'; import tooltip from '../../../vue_shared/directives/tooltip';
import loadingIcon from '../../../vue_shared/components/loading_icon.vue'; import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
......
/* global Flash */
import successSvg from 'icons/_icon_status_success.svg'; import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg'; import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll'; import simplePoll from '~/lib/utils/simple_poll';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon'; import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
......
/* global Flash */
import statusIcon from '../mr_widget_status_icon'; import statusIcon from '../mr_widget_status_icon';
import tooltip from '../../../vue_shared/directives/tooltip'; import tooltip from '../../../vue_shared/directives/tooltip';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
...@@ -27,12 +26,12 @@ export default { ...@@ -27,12 +26,12 @@ export default {
.then(res => res.json()) .then(res => res.json())
.then((res) => { .then((res) => {
eventHub.$emit('UpdateWidgetData', res); eventHub.$emit('UpdateWidgetData', res);
new Flash('The merge request can now be merged.', 'notice'); // eslint-disable-line new window.Flash('The merge request can now be merged.', 'notice'); // eslint-disable-line
$('.merge-request .detail-page-description .title').text(this.mr.title); $('.merge-request .detail-page-description .title').text(this.mr.title);
}) })
.catch(() => { .catch(() => {
this.isMakingRequest = false; this.isMakingRequest = false;
new Flash('Something went wrong. Please try again.'); // eslint-disable-line new window.Flash('Something went wrong. Please try again.'); // eslint-disable-line
}); });
}, },
}, },
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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