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 */ /* 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 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 || {};
......
<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;
/* 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';
......
/* 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';
......
/* 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';
......
/* 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 */
import Flash from './flash';
((global) => { ((global) => {
class LabelManager { class LabelManager {
constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) { 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 */ /* 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 */
...@@ -71,7 +70,7 @@ import './diff'; ...@@ -71,7 +70,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';
...@@ -164,7 +163,6 @@ $(function () { ...@@ -164,7 +163,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;
...@@ -249,13 +247,6 @@ $(function () { ...@@ -249,13 +247,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() {
......
/* 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,6 +17,7 @@ import Dropzone from 'dropzone'; ...@@ -18,6 +17,7 @@ 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 loadAwardsHandler from './awards_handler'; import loadAwardsHandler from './awards_handler';
import './autosave'; import './autosave';
...@@ -354,7 +354,7 @@ export default class Notes { ...@@ -354,7 +354,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;
...@@ -593,7 +593,7 @@ export default class Notes { ...@@ -593,7 +593,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) {
...@@ -1213,13 +1213,13 @@ export default class Notes { ...@@ -1213,13 +1213,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;
} }
} }
......
<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() {
......
<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) => {
......
/* 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 */ /* 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'; import { __, s__ } from './locale';
export default class Star { export default class Star {
......
/* 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 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
}); });
}, },
}, },
......
/* global Flash */ import Flash from '../flash';
import { import {
WidgetHeader, WidgetHeader,
WidgetMergeHelp, WidgetMergeHelp,
......
<script> <script>
/* global Flash */ import Flash from '../../../flash';
import markdownHeader from './header.vue'; import markdownHeader from './header.vue';
import markdownToolbar from './toolbar.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', () => { ...@@ -138,9 +138,9 @@ describe('IntegrationSettingsForm', () => {
deferred.resolve({ error: true, message: errorMessage, service_response: 'some error' }); deferred.resolve({ error: true, message: errorMessage, service_response: 'some error' });
const $flashContainer = $('.flash-container'); 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')).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', () => { it('should submit form if ajax request responds without any error in test', () => {
...@@ -168,7 +168,7 @@ describe('IntegrationSettingsForm', () => { ...@@ -168,7 +168,7 @@ describe('IntegrationSettingsForm', () => {
expect($flashAction).toBeDefined(); expect($flashAction).toBeDefined();
spyOn(integrationSettingsForm.$form, 'submit'); spyOn(integrationSettingsForm.$form, 'submit');
$flashAction.trigger('click'); $flashAction.get(0).click();
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled(); expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
}); });
...@@ -181,7 +181,7 @@ describe('IntegrationSettingsForm', () => { ...@@ -181,7 +181,7 @@ describe('IntegrationSettingsForm', () => {
deferred.reject(); 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', () => { it('should always call `toggleSubmitBtnState` with `false` once request is completed', () => {
......
...@@ -815,7 +815,7 @@ import '~/notes'; ...@@ -815,7 +815,7 @@ import '~/notes';
}); });
it('shows a flash message', () => { 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(); expect($('.flash-alert').is(':visible')).toBeTruthy();
}); });
...@@ -828,7 +828,7 @@ import '~/notes'; ...@@ -828,7 +828,7 @@ import '~/notes';
}); });
it('hides visible flash message', () => { 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(); 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