2021-04-17 20:07:23 +05:30
|
|
|
import * as Sentry from '@sentry/browser';
|
2022-03-02 08:16:31 +05:30
|
|
|
import Vue from 'vue';
|
|
|
|
import { GlAlert } from '@gitlab/ui';
|
|
|
|
import { __ } from '~/locale';
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
const FLASH_TYPES = {
|
|
|
|
ALERT: 'alert',
|
|
|
|
NOTICE: 'notice',
|
|
|
|
SUCCESS: 'success',
|
|
|
|
WARNING: 'warning',
|
|
|
|
};
|
|
|
|
|
2022-03-02 08:16:31 +05:30
|
|
|
const VARIANT_SUCCESS = 'success';
|
|
|
|
const VARIANT_WARNING = 'warning';
|
|
|
|
const VARIANT_DANGER = 'danger';
|
|
|
|
const VARIANT_INFO = 'info';
|
|
|
|
const VARIANT_TIP = 'tip';
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
const FLASH_CLOSED_EVENT = 'flashClosed';
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
const getCloseEl = (flashEl) => {
|
|
|
|
return flashEl.querySelector('.js-close-icon');
|
|
|
|
};
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
const hideFlash = (flashEl, fadeTransition = true) => {
|
|
|
|
if (fadeTransition) {
|
|
|
|
Object.assign(flashEl.style, {
|
2020-03-13 15:44:24 +05:30
|
|
|
transition: 'opacity 0.15s',
|
2018-03-17 18:26:18 +05:30
|
|
|
opacity: '0',
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2018-12-13 13:39:08 +05:30
|
|
|
flashEl.addEventListener(
|
|
|
|
'transitionend',
|
|
|
|
() => {
|
|
|
|
flashEl.remove();
|
|
|
|
window.dispatchEvent(new Event('resize'));
|
2021-12-11 22:18:48 +05:30
|
|
|
flashEl.dispatchEvent(new Event(FLASH_CLOSED_EVENT));
|
2018-12-13 13:39:08 +05:30
|
|
|
if (document.body.classList.contains('flash-shown'))
|
|
|
|
document.body.classList.remove('flash-shown');
|
|
|
|
},
|
|
|
|
{
|
|
|
|
once: true,
|
|
|
|
passive: true,
|
|
|
|
},
|
|
|
|
);
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
if (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
|
|
|
|
};
|
2017-09-10 17:25:29 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
const addDismissFlashClickListener = (flashEl, fadeTransition) => {
|
2021-09-04 01:27:46 +05:30
|
|
|
// 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));
|
2018-03-17 18:26:18 +05:30
|
|
|
};
|
|
|
|
|
2022-03-02 08:16:31 +05:30
|
|
|
/**
|
|
|
|
* Render an alert at the top of the page, or, optionally an
|
2022-07-16 23:28:13 +05:30
|
|
|
* arbitrary existing container. This alert is always dismissible.
|
2022-03-02 08:16:31 +05:30
|
|
|
*
|
2022-07-16 23:28:13 +05:30
|
|
|
* @example
|
|
|
|
* // Render a new alert
|
2022-06-21 17:19:12 +05:30
|
|
|
* import { createAlert, VARIANT_WARNING } from '~/flash';
|
2022-03-02 08:16:31 +05:30
|
|
|
*
|
|
|
|
* createAlert({ message: 'My error message' });
|
2022-06-21 17:19:12 +05:30
|
|
|
* createAlert({ message: 'My warning message', variant: VARIANT_WARNING });
|
2022-03-02 08:16:31 +05:30
|
|
|
*
|
2022-07-16 23:28:13 +05:30
|
|
|
* @example
|
|
|
|
* // Dismiss this alert programmatically
|
2022-03-02 08:16:31 +05:30
|
|
|
* const alert = createAlert({ message: 'Message' });
|
|
|
|
*
|
|
|
|
* // ...
|
|
|
|
*
|
|
|
|
* alert.dismiss();
|
|
|
|
*
|
2022-07-16 23:28:13 +05:30
|
|
|
* @example
|
|
|
|
* // Respond to the alert being dismissed
|
|
|
|
* createAlert({ message: 'Message', onDismiss: () => {} });
|
2022-03-02 08:16:31 +05:30
|
|
|
*
|
2022-07-16 23:28:13 +05:30
|
|
|
* @param {object} options - Options to control the flash message
|
|
|
|
* @param {string} options.message - Alert message text
|
2023-01-13 00:05:48 +05:30
|
|
|
* @param {string} [options.title] - Alert title
|
2022-07-16 23:28:13 +05:30
|
|
|
* @param {VARIANT_SUCCESS|VARIANT_WARNING|VARIANT_DANGER|VARIANT_INFO|VARIANT_TIP} [options.variant] - Which GlAlert variant to use; it defaults to VARIANT_DANGER.
|
|
|
|
* @param {object} [options.parent] - Reference to parent element under which alert needs to appear. Defaults to `document`.
|
|
|
|
* @param {Function} [options.onDismiss] - Handler to call when this alert is dismissed.
|
|
|
|
* @param {string} [options.containerSelector] - Selector for the container of the alert
|
2023-03-04 22:38:38 +05:30
|
|
|
* @param {boolean} [options.preservePrevious] - Set to `true` to preserve previous alerts. Defaults to `false`.
|
2022-07-16 23:28:13 +05:30
|
|
|
* @param {object} [options.primaryButton] - Object describing primary button of alert
|
|
|
|
* @param {string} [options.primaryButton.link] - Href of primary button
|
|
|
|
* @param {string} [options.primaryButton.text] - Text of primary button
|
|
|
|
* @param {Function} [options.primaryButton.clickHandler] - Handler to call when primary button is clicked on. The click event is sent as an argument.
|
|
|
|
* @param {object} [options.secondaryButton] - Object describing secondary button of alert
|
|
|
|
* @param {string} [options.secondaryButton.link] - Href of secondary button
|
|
|
|
* @param {string} [options.secondaryButton.text] - Text of secondary button
|
|
|
|
* @param {Function} [options.secondaryButton.clickHandler] - Handler to call when secondary button is clicked on. The click event is sent as an argument.
|
|
|
|
* @param {boolean} [options.captureError] - Whether to send error to Sentry
|
|
|
|
* @param {object} [options.error] - Error to be captured in Sentry
|
2022-03-02 08:16:31 +05:30
|
|
|
*/
|
|
|
|
const createAlert = function createAlert({
|
|
|
|
message,
|
2023-01-13 00:05:48 +05:30
|
|
|
title,
|
2022-03-02 08:16:31 +05:30
|
|
|
variant = VARIANT_DANGER,
|
|
|
|
parent = document,
|
|
|
|
containerSelector = '.flash-container',
|
2023-03-04 22:38:38 +05:30
|
|
|
preservePrevious = false,
|
2022-03-02 08:16:31 +05:30
|
|
|
primaryButton = null,
|
|
|
|
secondaryButton = null,
|
|
|
|
onDismiss = null,
|
|
|
|
captureError = false,
|
|
|
|
error = null,
|
|
|
|
}) {
|
|
|
|
if (captureError && error) Sentry.captureException(error);
|
|
|
|
|
|
|
|
const alertContainer = parent.querySelector(containerSelector);
|
|
|
|
if (!alertContainer) return null;
|
|
|
|
|
|
|
|
const el = document.createElement('div');
|
2023-03-04 22:38:38 +05:30
|
|
|
if (preservePrevious) {
|
|
|
|
alertContainer.appendChild(el);
|
|
|
|
} else {
|
|
|
|
alertContainer.replaceChildren(el);
|
|
|
|
}
|
2022-03-02 08:16:31 +05:30
|
|
|
|
|
|
|
return new Vue({
|
|
|
|
el,
|
|
|
|
components: {
|
|
|
|
GlAlert,
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
/**
|
|
|
|
* Public method to dismiss this alert and removes
|
|
|
|
* this Vue instance.
|
|
|
|
*/
|
|
|
|
dismiss() {
|
|
|
|
if (onDismiss) {
|
|
|
|
onDismiss();
|
|
|
|
}
|
|
|
|
this.$destroy();
|
2022-11-25 23:54:43 +05:30
|
|
|
this.$el.parentNode?.removeChild(this.$el);
|
2022-03-02 08:16:31 +05:30
|
|
|
},
|
|
|
|
},
|
|
|
|
render(h) {
|
|
|
|
const on = {};
|
|
|
|
|
|
|
|
on.dismiss = () => {
|
|
|
|
this.dismiss();
|
|
|
|
};
|
|
|
|
|
|
|
|
if (primaryButton?.clickHandler) {
|
|
|
|
on.primaryAction = (e) => {
|
|
|
|
primaryButton.clickHandler(e);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (secondaryButton?.clickHandler) {
|
|
|
|
on.secondaryAction = (e) => {
|
|
|
|
secondaryButton.clickHandler(e);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return h(
|
|
|
|
GlAlert,
|
|
|
|
{
|
|
|
|
props: {
|
2023-01-13 00:05:48 +05:30
|
|
|
title,
|
2022-03-02 08:16:31 +05:30
|
|
|
dismissible: true,
|
|
|
|
dismissLabel: __('Dismiss'),
|
|
|
|
variant,
|
|
|
|
primaryButtonLink: primaryButton?.link,
|
|
|
|
primaryButtonText: primaryButton?.text,
|
|
|
|
secondaryButtonLink: secondaryButton?.link,
|
|
|
|
secondaryButtonText: secondaryButton?.text,
|
|
|
|
},
|
2022-04-04 11:22:00 +05:30
|
|
|
attrs: {
|
|
|
|
'data-testid': `alert-${variant}`,
|
|
|
|
},
|
2022-03-02 08:16:31 +05:30
|
|
|
on,
|
|
|
|
},
|
|
|
|
message,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
export {
|
|
|
|
hideFlash,
|
2022-01-26 12:08:38 +05:30
|
|
|
addDismissFlashClickListener,
|
2020-03-13 15:44:24 +05:30
|
|
|
FLASH_TYPES,
|
2021-12-11 22:18:48 +05:30
|
|
|
FLASH_CLOSED_EVENT,
|
2022-03-02 08:16:31 +05:30
|
|
|
createAlert,
|
|
|
|
VARIANT_SUCCESS,
|
|
|
|
VARIANT_WARNING,
|
|
|
|
VARIANT_DANGER,
|
|
|
|
VARIANT_INFO,
|
|
|
|
VARIANT_TIP,
|
2020-03-13 15:44:24 +05:30
|
|
|
};
|