Commit e4e8e0fc authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'flash-es6-module' into 'master'

Flash is now a ES6 module

See merge request gitlab-org/gitlab-ce!14626
parents 1fb4215b b40bac3a
/* eslint-disable class-methods-use-this */
/* global Flash */
import _ from 'underscore';
import Cookies from 'js-cookie';
import { isInIssuePage, updateTooltipTitle } from './lib/utils/common_utils';
import Flash from './flash';
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
......
/* global Flash */
import Flash from '../flash';
import BalsamiqViewer from './balsamiq/balsamiq_viewer';
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;
}
......
/* eslint-disable class-methods-use-this */
/* global Flash */
import Flash from '../flash';
import FileTemplateTypeSelector from './template_selectors/type_selector';
import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
import DockerfileSelector from './template_selectors/dockerfile_selector';
......
/* global Flash */
import Flash from '../../flash';
import { handleLocationHash } from '../../lib/utils/common_utils';
export default class BlobViewer {
......
/* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren */
/* global BoardService */
/* global Flash */
import _ from 'underscore';
import Vue from 'vue';
import VueResource from 'vue-resource';
import Flash from '../flash';
import FilteredSearchBoards from './filtered_search_boards';
import eventHub from './eventhub';
import './models/issue';
......
......@@ -3,9 +3,9 @@
/* global MilestoneSelect */
/* global LabelsSelect */
/* global Sidebar */
/* global Flash */
import Vue from 'vue';
import Flash from '../../flash';
import eventHub from '../../sidebar/event_hub';
import AssigneeTitle from '../../sidebar/components/assignees/assignee_title';
import Assignees from '../../sidebar/components/assignees/assignees';
......
/* eslint-disable no-new */
/* global Flash */
import Vue from 'vue';
import Flash from '../../../flash';
import './lists_dropdown';
const ModalStore = gl.issueBoards.ModalStore;
......
/* eslint-disable no-new */
/* global Flash */
import Vue from 'vue';
import Flash from '../../../flash';
const Store = gl.issueBoards.BoardsStore;
......
/* eslint-disable no-new */
/* global Flash */
import Flash from './flash';
import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter';
......
/* global Flash */
import Vue from 'vue';
import Cookies from 'js-cookie';
import Flash from '../flash';
import Translate from '../vue_shared/translate';
import banner from './components/banner.vue';
import stageCodeComponent from './components/stage_code_component.vue';
......
<script>
/* global Flash */
import Flash from '../../flash';
import eventHub from '../eventhub';
import DeployKeysService from '../service';
import DeployKeysStore from '../store';
......
/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, max-len */
/* global CommentsStore */
/* global ResolveService */
/* global Flash */
import Vue from 'vue';
import Flash from '../../flash';
const ResolveBtn = Vue.extend({
props: {
......
/* global Flash */
/* global CommentsStore */
import Vue from 'vue';
import Flash from '../../flash';
import '../../vue_shared/vue_resource_interceptor';
window.gl = window.gl || {};
......
<script>
/* global Flash */
import Visibility from 'visibilityjs';
import Flash from '../../flash';
import EnvironmentsService from '../services/environments_service';
import environmentTable from './environments_table.vue';
import EnvironmentsStore from '../stores/environments_store';
......
<script>
/* global Flash */
import Visibility from 'visibilityjs';
import Flash from '../../flash';
import EnvironmentsService from '../services/environments_service';
import environmentTable from '../components/environments_table.vue';
import EnvironmentsStore from '../stores/environments_store';
......
/* global Flash */
import Ajax from '~/droplab/plugins/ajax';
import Filter from '~/droplab/plugins/filter';
import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
import './filtered_search_dropdown';
class DropdownEmoji extends gl.FilteredSearchDropdown {
......
/* global Flash */
import Ajax from '~/droplab/plugins/ajax';
import Filter from '~/droplab/plugins/filter';
import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
import './filtered_search_dropdown';
class DropdownNonUser extends gl.FilteredSearchDropdown {
......
/* global Flash */
import AjaxFilter from '~/droplab/plugins/ajax_filter';
import Flash from '../flash';
import AjaxFilter from '../droplab/plugins/ajax_filter';
import './filtered_search_dropdown';
import { addClassIfElementExists } from '../lib/utils/dom_utils';
......
import Flash from '../flash';
import FilteredSearchContainer from './container';
import RecentSearchesRoot from './recent_searches_root';
import RecentSearchesStore from './stores/recent_searches_store';
......@@ -36,7 +37,7 @@ class FilteredSearchManager {
.catch((error) => {
if (error.name === 'RecentSearchesServiceError') return undefined;
// 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
return [];
})
......
import AjaxCache from '../lib/utils/ajax_cache';
import '../flash'; /* global Flash */
import Flash from '../flash';
import FilteredSearchContainer from './container';
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() {
var hideFlash;
const hideFlash = (flashEl, fadeTransition = true) => {
if (fadeTransition) {
Object.assign(flashEl.style, {
transition: 'opacity .3s',
opacity: '0',
});
}
hideFlash = function() {
return $(this).fadeOut();
};
flashEl.addEventListener('transitionend', () => {
flashEl.remove();
}, {
once: true,
passive: true,
});
/**
* 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 (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
};
if (actionConfig) {
const actionLinkConfig = {
class: 'flash-action',
href: actionConfig.href || '#',
text: actionConfig.title
};
const createAction = config => `
<a
href="${config.href || '#'}"
class="flash-action"
${config.href ? '' : 'role="button"'}
>
${_.escape(config.title)}
</a>
`;
if (!actionConfig.href) {
actionLinkConfig.role = 'button';
}
const createFlashEl = (message, type, isInContentWrapper = false) => `
<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);
this.flashContainer.on('click', '.flash-action', actionConfig.clickHandler);
}
if (this.flashContainer.parent().hasClass('content-wrapper')) {
textDiv.addClass('container-fluid container-limited');
if (!flashContainer) return null;
const isInContentWrapper = flashContainer.parentNode.classList.contains('content-wrapper');
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;
/* global Flash */
import Vue from 'vue';
import Flash from '../flash';
import GroupFilterableList from './groups_filterable_list';
import GroupsComponent from './components/groups.vue';
import GroupFolder from './components/group_folder.vue';
......
/* global Flash */
import Flash from '../flash';
export default class IntegrationSettingsForm {
constructor(formSelector) {
......@@ -102,7 +102,7 @@ export default class IntegrationSettingsForm {
})
.done((res) => {
if (res.error) {
new Flash(`${res.message} ${res.service_response}`, null, null, {
new Flash(`${res.message} ${res.service_response}`, 'alert', document, {
title: 'Save anyway',
clickHandler: (e) => {
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 */
/* global IssuableIndex */
/* global Flash */
import _ from 'underscore';
import Flash from './flash';
export default {
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 */
/* global Flash */
import 'vendor/jquery.waitforimages';
import '~/lib/utils/text_utility';
import './flash';
import Flash from './flash';
import TaskList from './task_list';
import CreateMergeRequestDropdown from './create_merge_request_dropdown';
import IssuablesHelper from './helpers/issuables_helper';
......
<script>
/* global Flash */
import Visibility from 'visibilityjs';
import Poll from '../../lib/utils/poll';
import eventHub from '../event_hub';
......@@ -153,7 +152,7 @@ export default {
})
.catch(() => {
eventHub.$emit('close.form');
return new Flash('Error updating issue');
window.Flash('Error updating issue');
});
},
deleteIssuable() {
......@@ -167,7 +166,7 @@ export default {
})
.catch(() => {
eventHub.$emit('close.form');
return new Flash('Error deleting issue');
window.Flash('Error deleting issue');
});
},
},
......
<script>
/* global Flash */
import updateMixin from '../../mixins/update';
import markdownField from '../../../vue_shared/components/markdown/field.vue';
......
/* global Flash */
import Vue from 'vue';
import JobMediator from './job_details_mediator';
import jobHeader from './components/header.vue';
......
/* global Flash */
/* global Build */
import Visibility from 'visibilityjs';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import JobStore from './stores/job_store';
import JobService from './services/job_service';
......
/* 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 */
import Flash from './flash';
((global) => {
class LabelManager {
constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
......
/* 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 Aside */
......@@ -71,7 +70,7 @@ import './diff';
import './dropzone_input';
import './due_date_select';
import './files_comment_button';
import './flash';
import Flash from './flash';
import './gl_dropdown';
import './gl_field_error';
import './gl_field_errors';
......@@ -164,7 +163,6 @@ $(function () {
var $document = $(document);
var $window = $(window);
var $sidebarGutterToggle = $('.js-sidebar-toggle');
var $flash = $('.flash-container');
var bootstrapBreakpoint = bp.getBreakpointSize();
var fitSidebarForSize;
......@@ -249,13 +247,6 @@ $(function () {
// Form submitter
});
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
$body.on('ajax:complete, ajax:beforeSend, submit', 'form', function (e) {
var buttons;
......
/* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, no-new, no-param-reassign, max-len */
/* global ace */
/* global Flash */
import Vue from 'vue';
import Flash from '../../flash';
((global) => {
global.mergeConflicts = global.mergeConflicts || {};
......
/* eslint-disable new-cap, comma-dangle, no-new */
/* global Flash */
import Vue from 'vue';
import Flash from '../flash';
import initIssuableSidebar from '../init_issuable_sidebar';
import './merge_conflict_store';
import './merge_conflict_service';
......
/* eslint-disable no-new, class-methods-use-this */
/* global Flash */
/* global notes */
import Cookies from 'js-cookie';
import './flash';
import Flash from './flash';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import initChangesDropdown from './init_changes_dropdown';
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 */
/* global Flash */
/* global Sortable */
import Flash from './flash';
(function() {
this.Milestone = (function() {
function Milestone() {
......
/* eslint-disable no-new */
/* global Flash */
import Flash from './flash';
/**
* In each pipelines table we have a mini pipeline graph for each pipeline.
......
<script>
/* global Flash */
import _ from 'underscore';
import Flash from '../../flash';
import MonitoringService from '../services/monitoring_service';
import GraphGroup from './graph_group.vue';
import Graph from './graph.vue';
......
......@@ -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,
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 */
/* global Flash */
/* global Autosave */
/* global ResolveService */
/* global mrRefreshWidgetUrl */
......@@ -18,6 +17,7 @@ import Dropzone from 'dropzone';
import 'vendor/jquery.caret'; // required by jquery.atwho
import 'vendor/jquery.atwho';
import AjaxCache from '~/lib/utils/ajax_cache';
import Flash from './flash';
import CommentTypeToggle from './comment_type_toggle';
import loadAwardsHandler from './awards_handler';
import './autosave';
......@@ -354,7 +354,7 @@ export default class Notes {
Object.keys(noteEntity.commands_changes).length > 0) {
$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();
}
return;
......@@ -593,7 +593,7 @@ export default class Notes {
} else if ($form.hasClass('js-discussion-note-form')) {
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) {
......@@ -1213,13 +1213,13 @@ export default class Notes {
}
addFlash(...flashParams) {
this.flashInstance = new Flash(...flashParams);
this.flashContainer = new Flash(...flashParams);
}
clearFlash() {
if (this.flashInstance && this.flashInstance.flashContainer) {
this.flashInstance.flashContainer.hide();
this.flashInstance = null;
if (this.flashContainer) {
this.flashContainer.style.display = 'none';
this.flashContainer = null;
}
}
......
<script>
/* global Flash, Autosave */
/* global Autosave */
import { mapActions, mapGetters } from 'vuex';
import _ from 'underscore';
import autosize from 'vendor/autosize';
import Flash from '../../flash';
import '../../autosave';
import TaskList from '../../task_list';
import * as constants from '../constants';
......@@ -145,7 +146,7 @@
Flash(
'Something went wrong while adding your comment. Please try again.',
'alert',
$(this.$refs.commentForm),
this.$refs.commentForm,
);
}
} else {
......@@ -160,7 +161,7 @@
this.isSubmitting = false;
this.discard(false);
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.removePlaceholderNotes();
});
......
<script>
/* global Flash */
import { mapActions, mapGetters } from 'vuex';
import Flash from '../../flash';
import { SYSTEM_NOTE } from '../constants';
import issueNote from './issue_note.vue';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
......@@ -133,7 +133,7 @@
this.isReplying = true;
this.$nextTick(() => {
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;
callback(err);
});
......
<script>
/* global Flash */
import { mapGetters, mapActions } from 'vuex';
import Flash from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import issueNoteHeader from './issue_note_header.vue';
import issueNoteActions from './issue_note_actions.vue';
......@@ -101,7 +100,7 @@
this.isEditing = true;
this.$nextTick(() => {
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);
callback();
});
......
<script>
/* global Flash */
import { mapActions, mapGetters } from 'vuex';
import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
import emojiSmile from 'icons/_emoji_smile.svg';
import emojiSmiley from 'icons/_emoji_smiley.svg';
import Flash from '../../flash';
import { glEmojiTag } from '../../emoji';
import tooltip from '../../vue_shared/directives/tooltip';
......
<script>
/* global Flash */
import { mapGetters, mapActions } from 'vuex';
import Flash from '../../flash';
import store from '../stores/';
import * as constants from '../constants';
import issueNote from './issue_note.vue';
......
/* global Flash */
import Visibility from 'visibilityjs';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
import * as types from './mutation_types';
import * as utils from './utils';
......@@ -99,7 +99,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
eTagPoll.makeRequest();
$('.js-gfm-input').trigger('clear-commands-cache.atwho');
Flash('Commands applied', 'notice', $(noteData.flashContainer));
Flash('Commands applied', 'notice', noteData.flashContainer);
}
if (commandsChanges) {
......@@ -114,8 +114,8 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
.catch(() => {
Flash(
'Something went wrong while adding your award. Please try again.',
null,
$(noteData.flashContainer),
'alert',
noteData.flashContainer,
);
});
}
......@@ -126,7 +126,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
}
if (errors && errors.commands_only) {
Flash(errors.commands_only, 'notice', $(noteData.flashContainer));
Flash(errors.commands_only, 'notice', noteData.flashContainer);
}
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 */
/* global Flash */
import Flash from './flash';
(function() {
this.NotificationsDropdown = (function() {
......
<script>
/* global Flash */
import '~/flash';
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
......
......@@ -13,7 +13,7 @@
* 4. Commit widget
*/
/* global Flash */
import Flash from '../../flash';
import { borderlessStatusIconEntityMap } from '../../vue_shared/ci_status_icons';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
......
/* global Flash */
import '~/flash';
import Visibility from 'visibilityjs';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
import emptyState from '../components/empty_state.vue';
import errorState from '../components/error_state.vue';
......
/* global Flash */
import Vue from 'vue';
import Flash from '../flash';
import PipelinesMediator from './pipeline_details_mediatior';
import pipelineGraph from './components/graph/graph_component.vue';
import pipelineHeader from './components/header_component.vue';
......
/* global Flash */
import Visibility from 'visibilityjs';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import PipelineStore from './stores/pipeline_store';
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 */
/* global Flash */
import Flash from '../flash';
import { getPagePath } from '../lib/utils/common_utils';
((global) => {
......
/* eslint-disable no-new */
/* global Flash */
import Flash from '../flash';
import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown';
export default class ProtectedBranchEdit {
......@@ -57,7 +56,7 @@ export default class ProtectedBranchEdit {
},
},
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(() => {
this.$allowedToMergeDropdown.enable();
......
/* eslint-disable no-new */
/* global Flash */
import Flash from '../flash';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
export default class ProtectedTagEdit {
......@@ -43,7 +42,7 @@ export default class ProtectedTagEdit {
},
},
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(() => {
this.$allowedToCreateDropdownButton.enable();
......
<script>
/* global Flash */
import Flash from '../../flash';
import Store from '../stores/repo_store';
import RepoMixin from '../mixins/repo_mixin';
import Service from '../services/repo_service';
......
/* global Flash */
import Service from '../services/repo_service';
import Store from '../stores/repo_store';
import '../../flash';
import Flash from '../../flash';
const RepoHelper = {
monacoInstance: null,
......
/* global Flash */
import axios from 'axios';
import Store from '../stores/repo_store';
import Api from '../../api';
......
/* global Flash */
import Helper from '../helpers/repo_helper';
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 */
/* global Flash */
import Flash from './flash';
import Api from './api';
(function() {
......
/* global Flash */
import Flash from '../../../flash';
import AssigneeTitle from './assignee_title';
import Assignees from './assignees';
......
<script>
/* global Flash */
import Flash from '../../../flash';
import editForm from './edit_form.vue';
export default {
......
/* global Flash */
function isValidProjectId(id) {
return id > 0;
}
......@@ -38,7 +36,7 @@ class SidebarMoveIssue {
data: (searchTerm, callback) => {
this.mediator.fetchAutocompleteProjects(searchTerm)
.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 => `
<li>
......@@ -73,7 +71,7 @@ class SidebarMoveIssue {
this.mediator.moveIssue()
.catch(() => {
Flash('An error occurred while moving the issue.');
window.Flash('An error occurred while moving the issue.');
this.$confirmButton
.enable()
.removeClass('is-loading');
......
/* global Flash */
import Flash from '../flash';
import Service from './services/sidebar_service';
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 */
/* global Flash */
import Flash from './flash';
import { __, s__ } from './locale';
export default class Star {
......
/* global Flash */
import 'deckar01-task_list';
import Flash from './flash';
export default class TaskList {
constructor(options = {}) {
......
/* global Flash */
import '~/lib/utils/datetime_utility';
import Flash from '../../flash';
import MemoryUsage from './mr_widget_memory_usage';
import StatusIcon from './mr_widget_status_icon';
import MRWidgetService from '../services/mr_widget_service';
......
/* global Flash */
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon';
import MRWidgetAuthor from '../../components/mr_widget_author';
import eventHub from '../../event_hub';
......
/* global Flash */
import Flash from '../../../flash';
import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
import tooltip from '../../../vue_shared/directives/tooltip';
import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
......
/* global Flash */
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub';
......
/* global Flash */
import statusIcon from '../mr_widget_status_icon';
import tooltip from '../../../vue_shared/directives/tooltip';
import eventHub from '../../event_hub';
......@@ -27,12 +26,12 @@ export default {
.then(res => res.json())
.then((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);
})
.catch(() => {
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
});
},
},
......
/* global Flash */
import Flash from '../flash';
import {
WidgetHeader,
WidgetMergeHelp,
......
<script>
/* global Flash */
import Flash from '../../../flash';
import markdownHeader from './header.vue';
import markdownToolbar from './toolbar.vue';
......
import flash, {
createFlashEl,
createAction,
hideFlash,
} from '~/flash';
describe('Flash', () => {
describe('createFlashEl', () => {
let el;
beforeEach(() => {
el = document.createElement('div');
});
afterEach(() => {
el.innerHTML = '';
});
it('creates flash element with type', () => {
el.innerHTML = createFlashEl('testing', 'alert');
expect(
el.querySelector('.flash-alert'),
).not.toBeNull();
});
it('escapes text', () => {
el.innerHTML = createFlashEl('<script>alert("a");</script>', 'alert');
expect(
el.querySelector('.flash-text').textContent.trim(),
).toBe('<script>alert("a");</script>');
});
it('adds container classes when inside content wrapper', () => {
el.innerHTML = createFlashEl('testing', 'alert', true);
expect(
el.querySelector('.flash-text').classList.contains('container-fluid'),
).toBeTruthy();
expect(
el.querySelector('.flash-text').classList.contains('container-limited'),
).toBeTruthy();
});
});
describe('hideFlash', () => {
let el;
beforeEach(() => {
el = document.createElement('div');
el.className = 'js-testing';
});
it('sets transition style', () => {
hideFlash(el);
expect(
el.style.transition,
).toBe('opacity 0.3s');
});
it('sets opacity style', () => {
hideFlash(el);
expect(
el.style.opacity,
).toBe('0');
});
it('does not set styles when fadeTransition is false', () => {
hideFlash(el, false);
expect(
el.style.opacity,
).toBe('');
expect(
el.style.transition,
).toBe('');
});
it('removes element after transitionend', () => {
document.body.appendChild(el);
hideFlash(el);
el.dispatchEvent(new Event('transitionend'));
expect(
document.querySelector('.js-testing'),
).toBeNull();
});
it('calls event listener callback once', () => {
spyOn(el, 'remove').and.callThrough();
document.body.appendChild(el);
hideFlash(el);
el.dispatchEvent(new Event('transitionend'));
el.dispatchEvent(new Event('transitionend'));
expect(
el.remove.calls.count(),
).toBe(1);
});
});
describe('createAction', () => {
let el;
beforeEach(() => {
el = document.createElement('div');
});
it('creates link with href', () => {
el.innerHTML = createAction({
href: 'testing',
title: 'test',
});
expect(
el.querySelector('.flash-action').href,
).toContain('testing');
});
it('uses hash as href when no href is present', () => {
el.innerHTML = createAction({
title: 'test',
});
expect(
el.querySelector('.flash-action').href,
).toContain('#');
});
it('adds role when no href is present', () => {
el.innerHTML = createAction({
title: 'test',
});
expect(
el.querySelector('.flash-action').getAttribute('role'),
).toBe('button');
});
it('escapes the title text', () => {
el.innerHTML = createAction({
title: '<script>alert("a")</script>',
});
expect(
el.querySelector('.flash-action').textContent.trim(),
).toBe('<script>alert("a")</script>');
});
});
describe('createFlash', () => {
describe('no flash-container', () => {
it('does not add to the DOM', () => {
const flashEl = flash('testing');
expect(
flashEl,
).toBeNull();
expect(
document.querySelector('.flash-alert'),
).toBeNull();
});
});
describe('with flash-container', () => {
beforeEach(() => {
document.body.innerHTML += `
<div class="content-wrapper js-content-wrapper">
<div class="flash-container"></div>
</div>
`;
});
afterEach(() => {
document.querySelector('.js-content-wrapper').remove();
});
it('adds flash element into container', () => {
flash('test');
expect(
document.querySelector('.flash-alert'),
).not.toBeNull();
});
it('adds flash into specified parent', () => {
flash(
'test',
'alert',
document.querySelector('.content-wrapper'),
);
expect(
document.querySelector('.content-wrapper .flash-alert'),
).not.toBeNull();
});
it('adds container classes when inside content-wrapper', () => {
flash('test');
expect(
document.querySelector('.flash-text').className,
).toBe('flash-text container-fluid container-limited');
});
it('does not add container when outside of content-wrapper', () => {
document.querySelector('.content-wrapper').className = 'js-content-wrapper';
flash('test');
expect(
document.querySelector('.flash-text').className.trim(),
).toBe('flash-text');
});
it('removes element after clicking', () => {
flash('test', 'alert', document, null, false);
document.querySelector('.flash-alert').click();
expect(
document.querySelector('.flash-alert'),
).toBeNull();
});
describe('with actionConfig', () => {
it('adds action link', () => {
flash(
'test',
'alert',
document,
{
title: 'test',
},
);
expect(
document.querySelector('.flash-action'),
).not.toBeNull();
});
it('calls actionConfig clickHandler on click', () => {
const actionConfig = {
title: 'test',
clickHandler: jasmine.createSpy('actionConfig'),
};
flash(
'test',
'alert',
document,
actionConfig,
);
document.querySelector('.flash-action').click();
expect(
actionConfig.clickHandler,
).toHaveBeenCalled();
});
});
});
});
});
......@@ -138,9 +138,9 @@ describe('IntegrationSettingsForm', () => {
deferred.resolve({ error: true, message: errorMessage, service_response: 'some error' });
const $flashContainer = $('.flash-container');
expect($flashContainer.find('.flash-text').text()).toEqual('Test failed. some error');
expect($flashContainer.find('.flash-text').text().trim()).toEqual('Test failed. some error');
expect($flashContainer.find('.flash-action')).toBeDefined();
expect($flashContainer.find('.flash-action').text()).toEqual('Save anyway');
expect($flashContainer.find('.flash-action').text().trim()).toEqual('Save anyway');
});
it('should submit form if ajax request responds without any error in test', () => {
......@@ -168,7 +168,7 @@ describe('IntegrationSettingsForm', () => {
expect($flashAction).toBeDefined();
spyOn(integrationSettingsForm.$form, 'submit');
$flashAction.trigger('click');
$flashAction.get(0).click();
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
});
......@@ -181,7 +181,7 @@ describe('IntegrationSettingsForm', () => {
deferred.reject();
expect($('.flash-container .flash-text').text()).toEqual(errorMessage);
expect($('.flash-container .flash-text').text().trim()).toEqual(errorMessage);
});
it('should always call `toggleSubmitBtnState` with `false` once request is completed', () => {
......
......@@ -815,7 +815,7 @@ import '~/notes';
});
it('shows a flash message', () => {
this.notes.addFlash('Error message', FLASH_TYPE_ALERT, this.notes.parentTimeline);
this.notes.addFlash('Error message', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
expect($('.flash-alert').is(':visible')).toBeTruthy();
});
......@@ -828,7 +828,7 @@ import '~/notes';
});
it('hides visible flash message', () => {
this.notes.addFlash('Error message 1', FLASH_TYPE_ALERT, this.notes.parentTimeline);
this.notes.addFlash('Error message 1', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
this.notes.clearFlash();
......
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