/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
import ClayAlert from '@clayui/alert';
import {render} from '@liferay/frontend-js-react-web';
import React from 'react';
import {unmountComponentAtNode} from 'react-dom';
import buildFragment from '../../util/build_fragment';
const DEFAULT_ALERT_CONTAINER_ID = 'ToastAlertContainer';
const DEFAULT_RENDER_DATA = {
portletId: 'UNKNOWN_PORTLET_ID',
};
const DEFAULT_TOAST_TYPE_TITLES = {
danger: Liferay.Language.get('error'),
info: Liferay.Language.get('info'),
success: Liferay.Language.get('success'),
warning: Liferay.Language.get('warning'),
};
const TOAST_AUTO_CLOSE_INTERVAL = 5000;
const TPL_ALERT_CONTAINER = `
<div class="alert-container container">
<div class="alert-notifications alert-notifications-fixed" id=${DEFAULT_ALERT_CONTAINER_ID}></div>
</div>
`;
const getRootElement = ({container, containerId}) => {
if (container || containerId) {
container = container || document.getElementById(containerId);
if (container) {
const child = document.createElement('div');
container.appendChild(child);
return child;
}
}
let alertFixed = document.getElementById(DEFAULT_ALERT_CONTAINER_ID);
if (!alertFixed) {
alertFixed = buildFragment(TPL_ALERT_CONTAINER).querySelector(
'.alert-container.container'
);
alertFixed = document.body.appendChild(alertFixed);
}
// Creates a fragment to prevent React from unmounting the alert container
container = document.createElement('div');
container.className = 'mb-3';
const fragmentContainer = document.querySelector(
`.alert-notifications.alert-notifications-fixed`
);
fragmentContainer.appendChild(container);
return container;
};
/**
* Function that implements the Toast pattern, which allows to present feedback
* to user actions as a toast message in the lower left corner of the page
*
* @param {number|boolean} autoClose Flag to indicate alert should automatically call onClose.
* It also accepts a duration (in ms) which indicates how long to wait. If true is passed in, the
* timeout will be 10000ms. See https://clayui.com/docs/components/alert.html for more details.
* @param {HTMLElement} container Target element where the toast React component should be mounted.
* @param {string} containerId The id of the element where the toast React component should be mounted.
* @param {string|HTML} message The message to show in the toast notification
* @param {string|HTML} title The title associated with the message
* @param {string} displayType The displayType of notification to show. It can be one of the
* following: 'danger', 'info', 'success', 'warning'
* @return {ClayToast} The Alert toast created
* @review
*/
function openToast({
autoClose = TOAST_AUTO_CLOSE_INTERVAL,
container,
containerId,
message = '',
onClick = () => {},
onClose = () => {},
renderData = DEFAULT_RENDER_DATA,
title,
toastProps = {},
type = 'success',
variant,
}) {
const rootElement = getRootElement({container, containerId});
unmountComponentAtNode(rootElement);
const onCloseFn = (event) => {
if (onClose) {
onClose({event});
}
if (!event || !event.defaultPrevented) {
if (!container || !containerId) {
rootElement.parentNode.removeChild(rootElement);
}
unmountComponentAtNode(rootElement);
}
};
let titleHTML =
title === undefined ? DEFAULT_TOAST_TYPE_TITLES[type] : title;
if (titleHTML) {
titleHTML = titleHTML.replace(/:$/, '');
titleHTML = `<strong class="lead">${titleHTML}:</strong>`;
}
else {
titleHTML = '';
}
render(
<ClayAlert
autoClose={autoClose}
displayType={type}
onClick={(event) => onClick({event, onClose: onCloseFn})}
onClose={onCloseFn}
variant={variant}
{...toastProps}
>
<div
dangerouslySetInnerHTML={{
__html: `${titleHTML}${message}`,
}}
/>
</ClayAlert>,
renderData,
rootElement
);
}
export {openToast};
export default openToast;