Skip to content
Snippets Groups Projects
Verified Commit fa2af5e0 authored by Phil Hughes's avatar Phil Hughes
Browse files

Flash is now a ES6 module

Reduced the technical debt around our JS flash function by making it a
module that is imported rather than relying on the global function.
The global function still exists mainly for technical debt with how
some requests are being completed, but new JS should import the module
directly.

Also reduces some tech debt in the file by removing the need for jQuery.
Instead Flash is now 100% vanilla JS.
parent 99806914
No related branches found
No related tags found
No related merge requests found
Showing
with 86 additions and 101 deletions
/* 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) => {
flashEl.style.transition = 'opacity .3s'; // eslint-disable-line no-param-reassign
flashEl.style.opacity = '0'; // eslint-disable-line no-param-reassign
 
hideFlash = function() {
return $(this).fadeOut();
};
flashEl.addEventListener('transitionend', () => {
flashEl.remove();
}, {
once: 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);
const createAction = config => `
<a
href="${config.href || '#'}"
class="flash-action"
${config.href ? 'role="button"' : ''}
>
${_.escape(config.title)}
</a>
`;
 
if (actionConfig) {
const actionLinkConfig = {
class: 'flash-action',
href: actionConfig.href || '#',
text: actionConfig.title
};
const createFlashEl = (message, type) => `
<div
class="flash-${type}"
>
<div
class="flash-text"
>
${_.escape(message)}
</div>
</div>
`;
 
if (!actionConfig.href) {
actionLinkConfig.role = 'button';
}
const Flash = function Flash(message, type = 'alert', parent = document, actionConfig = null) {
const flashContainer = parent.querySelector('.flash-container');
flashContainer.innerHTML = createFlashEl(message, type);
 
actionLink = $('<a/>', actionLinkConfig);
const flashEl = flashContainer.querySelector(`.flash-${type}`);
flashEl.addEventListener('click', () => hideFlash(flashEl));
 
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 (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;
})();
if (flashContainer.parentNode.classList.contains('content-wrapper')) {
const flashText = flashEl.querySelector('.flash-text');
flashText.classList.add('container-fluid');
flashText.classList.add('container-limited');
}
flashContainer.style.display = 'block';
return flashContainer;
};
export {
Flash as default,
createFlashEl,
hideFlash,
};
window.Flash = Flash;
/* 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';
Loading
Loading
/* global Flash */
import Flash from '../flash';
 
export default class IntegrationSettingsForm {
constructor(formSelector) {
Loading
Loading
@@ -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();
Loading
Loading
/* 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 } = {}) {
Loading
Loading
/* 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';
Loading
Loading
<script>
/* global Flash */
import Visibility from 'visibilityjs';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
import eventHub from '../event_hub';
import Service from '../services/index';
Loading
Loading
/* 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';
Loading
Loading
/* 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 } = {}) {
Loading
Loading
/* 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 */
 
Loading
Loading
@@ -75,7 +74,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';
Loading
Loading
@@ -168,7 +167,6 @@ $(function () {
var $document = $(document);
var $window = $(window);
var $sidebarGutterToggle = $('.js-sidebar-toggle');
var $flash = $('.flash-container');
var bootstrapBreakpoint = bp.getBreakpointSize();
var fitSidebarForSize;
 
Loading
Loading
@@ -253,13 +251,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;
Loading
Loading
/* 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 || {};
Loading
Loading
/* 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';
Loading
Loading
/* 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';
Loading
Loading
/* 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() {
Loading
Loading
/* eslint-disable no-new */
/* global Flash */
import Flash from './flash';
 
/**
* In each pipelines table we have a mini pipeline graph for each pipeline.
Loading
Loading
<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';
Loading
Loading
Loading
Loading
@@ -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 */
Loading
Loading
@@ -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';
Loading
Loading
@@ -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); // TODO: CHECK THIS!
this.refresh();
}
return;
Loading
Loading
<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';
Loading
Loading
@@ -145,7 +146,7 @@
Flash(
'Something went wrong while adding your comment. Please try again.',
'alert',
$(this.$refs.commentForm),
this.$refs.commentForm,
);
}
} else {
Loading
Loading
@@ -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();
});
Loading
Loading
<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';
Loading
Loading
@@ -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);
});
Loading
Loading
<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';
Loading
Loading
@@ -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();
});
Loading
Loading
<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';
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment