Source: modal/components/SimpleInputModal.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 ClayButton from '@clayui/button';
  16. import {ClayCheckbox} from '@clayui/form';
  17. import ClayIcon from '@clayui/icon';
  18. import ClayModal, {useModal} from '@clayui/modal';
  19. import {useIsMounted} from '@liferay/frontend-js-react-web';
  20. import React, {useState} from 'react';
  21. import fetch from '../../util/fetch.es';
  22. import navigate from '../../util/navigate.es';
  23. /**
  24. * Manipulates small amounts of data with a form shown inside a modal.
  25. */
  26. const SimpleInputModal = ({
  27. alert,
  28. checkboxFieldLabel,
  29. checkboxFieldName,
  30. checkboxFieldValue,
  31. closeModal,
  32. dialogTitle,
  33. formSubmitURL,
  34. idFieldName,
  35. idFieldValue,
  36. initialVisible,
  37. mainFieldLabel,
  38. mainFieldName,
  39. namespace,
  40. onFormSuccess,
  41. placeholder,
  42. }) => {
  43. const isMounted = useIsMounted();
  44. const [errorMessage, setErrorMessage] = useState();
  45. const [loadingResponse, setLoadingResponse] = useState(false);
  46. const [visible, setVisible] = useState(initialVisible);
  47. const [inputValue, setInputValue] = useState('');
  48. const [isChecked, setChecked] = useState(checkboxFieldValue);
  49. const handleFormError = (responseContent) => {
  50. setErrorMessage(responseContent.error || '');
  51. };
  52. const _handleSubmit = (event) => {
  53. event.preventDefault();
  54. const formData = new FormData(
  55. document.querySelector(`#${namespace}form`)
  56. );
  57. fetch(formSubmitURL, {
  58. body: formData,
  59. method: 'POST',
  60. })
  61. .then((response) => response.json())
  62. .then((responseContent) => {
  63. if (isMounted()) {
  64. if (responseContent.error) {
  65. setLoadingResponse(false);
  66. handleFormError(responseContent);
  67. }
  68. else {
  69. setVisible(false);
  70. closeModal();
  71. if (responseContent.redirectURL) {
  72. navigate(responseContent.redirectURL);
  73. }
  74. else {
  75. if (onFormSuccess) {
  76. onFormSuccess({
  77. ...responseContent,
  78. redirectURL:
  79. responseContent.redirectURL || '',
  80. });
  81. }
  82. }
  83. }
  84. }
  85. })
  86. .catch((response) => {
  87. handleFormError(response);
  88. });
  89. setLoadingResponse(true);
  90. };
  91. const {observer, onClose} = useModal({
  92. onClose: () => {
  93. setVisible(false);
  94. closeModal();
  95. },
  96. });
  97. return (
  98. visible && (
  99. <ClayModal observer={observer} size="md">
  100. <ClayModal.Header>{dialogTitle}</ClayModal.Header>
  101. <form id={`${namespace}form`} onSubmit={_handleSubmit}>
  102. <ClayModal.Body>
  103. {alert && alert.message && alert.title && (
  104. <ClayAlert
  105. displayType={alert.style}
  106. title={alert.title}
  107. >
  108. {alert.message}
  109. </ClayAlert>
  110. )}
  111. <input
  112. name={`${namespace}${idFieldName}`}
  113. type="hidden"
  114. value={idFieldValue}
  115. />
  116. <div
  117. className={`form-group ${
  118. errorMessage ? 'has-error' : ''
  119. }`}
  120. >
  121. <label
  122. className="control-label"
  123. htmlFor={`${namespace}${mainFieldName}`}
  124. >
  125. {mainFieldLabel}
  126. <span className="reference-mark">
  127. <ClayIcon symbol="asterisk" />
  128. </span>
  129. </label>
  130. <input
  131. autoFocus
  132. className="form-control"
  133. disabled={loadingResponse}
  134. id={`${namespace}${mainFieldName}`}
  135. name={`${namespace}${mainFieldName}`}
  136. onChange={(event) =>
  137. setInputValue(event.target.value)
  138. }
  139. placeholder={placeholder}
  140. required
  141. type="text"
  142. value={inputValue}
  143. />
  144. {errorMessage && (
  145. <div className="form-feedback-item">
  146. <ClayIcon
  147. className="inline-item inline-item-before"
  148. symbol="exclamation-full"
  149. />
  150. {errorMessage}
  151. </div>
  152. )}
  153. </div>
  154. {checkboxFieldName && checkboxFieldLabel && (
  155. <div className="form-check">
  156. <ClayCheckbox
  157. checked={isChecked}
  158. disabled={loadingResponse}
  159. label={checkboxFieldLabel}
  160. name={`${namespace}${checkboxFieldName}`}
  161. onChange={() =>
  162. setChecked((isChecked) => !isChecked)
  163. }
  164. />
  165. </div>
  166. )}
  167. </ClayModal.Body>
  168. <ClayModal.Footer
  169. last={
  170. <ClayButton.Group spaced>
  171. <ClayButton
  172. disabled={loadingResponse}
  173. displayType="secondary"
  174. onClick={onClose}
  175. >
  176. {Liferay.Language.get('cancel')}
  177. </ClayButton>
  178. <ClayButton
  179. disabled={loadingResponse}
  180. displayType="primary"
  181. type="submit"
  182. >
  183. {loadingResponse && (
  184. <span className="inline-item inline-item-before">
  185. <span
  186. aria-hidden="true"
  187. className="loading-animation"
  188. ></span>
  189. </span>
  190. )}
  191. {Liferay.Language.get('save')}
  192. </ClayButton>
  193. </ClayButton.Group>
  194. }
  195. />
  196. </form>
  197. </ClayModal>
  198. )
  199. );
  200. };
  201. export default SimpleInputModal;