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
|
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 FLASH_CLOSED_EVENT = 'flashClosed';
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'));
flashEl.dispatchEvent(new Event(FLASH_CLOSED_EVENT));
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 addDismissFlashClickListener = (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));
}
}
addDismissFlashClickListener(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;
};
export {
createFlash as default,
hideFlash,
addDismissFlashClickListener,
FLASH_TYPES,
FLASH_CLOSED_EVENT,
};
|