1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
import * as Sentry from '@sentry/browser';
import { escape } from 'lodash';
import { spriteIcon } from './lib/utils/common_utils';
const FLASH_TYPES = {
ALERT: 'alert',
NOTICE: 'notice',
SUCCESS: 'success',
WARNING: 'warning',
};
const getCloseEl = (flashEl) => {
return flashEl.querySelector('.js-close-icon');
};
const hideFlash = (flashEl, fadeTransition = true) => {
if (fadeTransition) {
Object.assign(flashEl.style, {
transition: 'opacity 0.15s',
opacity: '0',
});
}
flashEl.addEventListener(
'transitionend',
() => {
flashEl.remove();
window.dispatchEvent(new Event('resize'));
if (document.body.classList.contains('flash-shown'))
document.body.classList.remove('flash-shown');
},
{
once: true,
passive: true,
},
);
if (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
};
const createAction = (config) => `
<a
href="${config.href || '#'}"
class="flash-action"
${config.href ? '' : 'role="button"'}
>
${escape(config.title)}
</a>
`;
const createFlashEl = (message, type) => `
<div class="flash-${type}">
<div class="flash-text">
${escape(message)}
<div class="close-icon-wrapper js-close-icon">
${spriteIcon('close', 'close-icon')}
</div>
</div>
</div>
`;
const removeFlashClickListener = (flashEl, fadeTransition) => {
// There are some flash elements which do not have a closeEl.
// https://gitlab.com/gitlab-org/gitlab/blob/763426ef344488972eb63ea5be8744e0f8459e6b/ee/app/views/layouts/header/_read_only_banner.html.haml
getCloseEl(flashEl)?.addEventListener('click', () => hideFlash(flashEl, fadeTransition));
};
/*
* 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 {Object} options Options to control the flash message
* @param {String} options.message Flash message text
* @param {String} options.type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
* @param {Object} options.parent Reference to parent element under which Flash needs to appear
* @param {Object} options.actionConfig 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} options.fadeTransition Boolean to determine whether to fade the alert out
* @param {Boolean} options.captureError Boolean to determine whether to send error to sentry
* @param {Object} options.error Error to be captured in sentry
*/
const createFlash = function createFlash({
message,
type = FLASH_TYPES.ALERT,
parent = document,
actionConfig = null,
fadeTransition = true,
addBodyClass = false,
captureError = false,
error = null,
}) {
const flashContainer = parent.querySelector('.flash-container');
if (!flashContainer) return null;
flashContainer.innerHTML = createFlashEl(message, type);
const flashEl = flashContainer.querySelector(`.flash-${type}`);
if (actionConfig) {
flashEl.insertAdjacentHTML('beforeend', createAction(actionConfig));
if (actionConfig.clickHandler) {
flashEl
.querySelector('.flash-action')
.addEventListener('click', (e) => actionConfig.clickHandler(e));
}
}
removeFlashClickListener(flashEl, fadeTransition);
flashContainer.classList.add('gl-display-block');
if (addBodyClass) document.body.classList.add('flash-shown');
if (captureError && error) Sentry.captureException(error);
flashContainer.close = () => {
getCloseEl(flashEl).click();
};
return flashContainer;
};
/*
* 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`, `success`, `warning` 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 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 deprecatedCreateFlash = function deprecatedCreateFlash(
message,
type,
parent,
actionConfig,
fadeTransition,
addBodyClass,
) {
return createFlash({ message, type, parent, actionConfig, fadeTransition, addBodyClass });
};
export {
createFlash as default,
deprecatedCreateFlash,
createFlashEl,
createAction,
hideFlash,
removeFlashClickListener,
FLASH_TYPES,
};
window.Flash = createFlash;
|