Source: toast/commands/OpenToast.es.js

  1. /**
  2. * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or modify it under
  5. * the terms of the GNU Lesser General Public License as published by the Free
  6. * Software Foundation; either version 2.1 of the License, or (at your option)
  7. * any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. * details.
  13. */
  14. import ClayAlert from '@clayui/alert';
  15. import {render} from '@liferay/frontend-js-react-web';
  16. import React from 'react';
  17. import {unmountComponentAtNode} from 'react-dom';
  18. import buildFragment from '../../util/build_fragment';
  19. const DEFAULT_ALERT_CONTAINER_ID = 'ToastAlertContainer';
  20. const DEFAULT_RENDER_DATA = {
  21. portletId: 'UNKNOWN_PORTLET_ID',
  22. };
  23. const DEFAULT_TOAST_TYPE_TITLES = {
  24. danger: Liferay.Language.get('error'),
  25. info: Liferay.Language.get('info'),
  26. success: Liferay.Language.get('success'),
  27. warning: Liferay.Language.get('warning'),
  28. };
  29. const TOAST_AUTO_CLOSE_INTERVAL = 5000;
  30. const TPL_ALERT_CONTAINER = `
  31. <div class="alert-container container">
  32. <div class="alert-notifications alert-notifications-fixed" id=${DEFAULT_ALERT_CONTAINER_ID}></div>
  33. </div>
  34. `;
  35. const getRootElement = ({container, containerId}) => {
  36. if (container || containerId) {
  37. container = container || document.getElementById(containerId);
  38. if (container) {
  39. const child = document.createElement('div');
  40. container.appendChild(child);
  41. return child;
  42. }
  43. }
  44. let alertFixed = document.getElementById(DEFAULT_ALERT_CONTAINER_ID);
  45. if (!alertFixed) {
  46. alertFixed = buildFragment(TPL_ALERT_CONTAINER).querySelector(
  47. '.alert-container.container'
  48. );
  49. alertFixed = document.body.appendChild(alertFixed);
  50. }
  51. // Creates a fragment to prevent React from unmounting the alert container
  52. container = document.createElement('div');
  53. container.className = 'mb-3';
  54. const fragmentContainer = document.querySelector(
  55. `.alert-notifications.alert-notifications-fixed`
  56. );
  57. fragmentContainer.appendChild(container);
  58. return container;
  59. };
  60. /**
  61. * Function that implements the Toast pattern, which allows to present feedback
  62. * to user actions as a toast message in the lower left corner of the page
  63. *
  64. * @param {number|boolean} autoClose Flag to indicate alert should automatically call onClose.
  65. * It also accepts a duration (in ms) which indicates how long to wait. If true is passed in, the
  66. * timeout will be 10000ms. See https://clayui.com/docs/components/alert.html for more details.
  67. * @param {HTMLElement} container Target element where the toast React component should be mounted.
  68. * @param {string} containerId The id of the element where the toast React component should be mounted.
  69. * @param {string|HTML} message The message to show in the toast notification
  70. * @param {string|HTML} title The title associated with the message
  71. * @param {string} displayType The displayType of notification to show. It can be one of the
  72. * following: 'danger', 'info', 'success', 'warning'
  73. * @return {ClayToast} The Alert toast created
  74. * @review
  75. */
  76. function openToast({
  77. autoClose = TOAST_AUTO_CLOSE_INTERVAL,
  78. container,
  79. containerId,
  80. message = '',
  81. onClick = () => {},
  82. onClose = () => {},
  83. renderData = DEFAULT_RENDER_DATA,
  84. title,
  85. toastProps = {},
  86. type = 'success',
  87. variant,
  88. }) {
  89. const rootElement = getRootElement({container, containerId});
  90. unmountComponentAtNode(rootElement);
  91. const onCloseFn = (event) => {
  92. if (onClose) {
  93. onClose({event});
  94. }
  95. if (!event || !event.defaultPrevented) {
  96. if (!container || !containerId) {
  97. rootElement.parentNode.removeChild(rootElement);
  98. }
  99. unmountComponentAtNode(rootElement);
  100. }
  101. };
  102. let titleHTML =
  103. title === undefined ? DEFAULT_TOAST_TYPE_TITLES[type] : title;
  104. if (titleHTML) {
  105. titleHTML = titleHTML.replace(/:$/, '');
  106. titleHTML = `<strong class="lead">${titleHTML}:</strong>`;
  107. }
  108. else {
  109. titleHTML = '';
  110. }
  111. render(
  112. <ClayAlert
  113. autoClose={autoClose}
  114. displayType={type}
  115. onClick={(event) => onClick({event, onClose: onCloseFn})}
  116. onClose={onCloseFn}
  117. variant={variant}
  118. {...toastProps}
  119. >
  120. <div
  121. dangerouslySetInnerHTML={{
  122. __html: `${titleHTML}${message}`,
  123. }}
  124. />
  125. </ClayAlert>,
  126. renderData,
  127. rootElement
  128. );
  129. }
  130. export {openToast};
  131. export default openToast;