PageDeleteModal.jsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import React, { useState } from 'react';
  2. import PropTypes from 'prop-types';
  3. import {
  4. Modal, ModalHeader, ModalBody, ModalFooter,
  5. } from 'reactstrap';
  6. import { withTranslation } from 'react-i18next';
  7. import { apiPost } from '~/client/util/apiv1-client';
  8. import ApiErrorMessageList from './PageManagement/ApiErrorMessageList';
  9. const deleteIconAndKey = {
  10. completely: {
  11. color: 'danger',
  12. icon: 'fire',
  13. translationKey: 'completely',
  14. },
  15. temporary: {
  16. color: 'primary',
  17. icon: 'trash',
  18. translationKey: 'page',
  19. },
  20. };
  21. const PageDeleteModal = (props) => {
  22. const {
  23. t, isOpen, onClose, isDeleteCompletelyModal, pageId, revisionId, path, isAbleToDeleteCompletely,
  24. } = props;
  25. const [isDeleteRecursively, setIsDeleteRecursively] = useState(true);
  26. const [isDeleteCompletely, setIsDeleteCompletely] = useState(isDeleteCompletelyModal && isAbleToDeleteCompletely);
  27. const deleteMode = isDeleteCompletely ? 'completely' : 'temporary';
  28. const [errs, setErrs] = useState(null);
  29. function changeIsDeleteRecursivelyHandler() {
  30. setIsDeleteRecursively(!isDeleteRecursively);
  31. }
  32. function changeIsDeleteCompletelyHandler() {
  33. if (!isAbleToDeleteCompletely) {
  34. return;
  35. }
  36. setIsDeleteCompletely(!isDeleteCompletely);
  37. }
  38. async function deletePage() {
  39. setErrs(null);
  40. try {
  41. // control flag
  42. // If is it not true, Request value must be `null`.
  43. const recursively = isDeleteRecursively ? true : null;
  44. const completely = isDeleteCompletely ? true : null;
  45. const response = await apiPost('/pages.remove', {
  46. page_id: pageId,
  47. revision_id: revisionId,
  48. recursively,
  49. completely,
  50. });
  51. const trashPagePath = response.page.path;
  52. window.location.href = encodeURI(trashPagePath);
  53. }
  54. catch (err) {
  55. setErrs(err);
  56. }
  57. }
  58. async function deleteButtonHandler() {
  59. deletePage();
  60. }
  61. function renderDeleteRecursivelyForm() {
  62. return (
  63. <div className="custom-control custom-checkbox custom-checkbox-warning">
  64. <input
  65. className="custom-control-input"
  66. id="deleteRecursively"
  67. type="checkbox"
  68. checked={isDeleteRecursively}
  69. onChange={changeIsDeleteRecursivelyHandler}
  70. />
  71. <label className="custom-control-label" htmlFor="deleteRecursively">
  72. { t('modal_delete.delete_recursively') }
  73. <p className="form-text text-muted mt-0"><code>{path}</code> { t('modal_delete.recursively') }</p>
  74. </label>
  75. </div>
  76. );
  77. }
  78. function renderDeleteCompletelyForm() {
  79. return (
  80. <div className="custom-control custom-checkbox custom-checkbox-danger">
  81. <input
  82. className="custom-control-input"
  83. name="completely"
  84. id="deleteCompletely"
  85. type="checkbox"
  86. disabled={!isAbleToDeleteCompletely}
  87. checked={isDeleteCompletely}
  88. onChange={changeIsDeleteCompletelyHandler}
  89. />
  90. <label className="custom-control-label text-danger" htmlFor="deleteCompletely">
  91. { t('modal_delete.delete_completely') }
  92. <p className="form-text text-muted mt-0"> { t('modal_delete.completely') }</p>
  93. </label>
  94. {!isAbleToDeleteCompletely
  95. && (
  96. <p className="alert alert-warning p-2 my-0">
  97. <i className="icon-ban icon-fw"></i>{ t('modal_delete.delete_completely_restriction') }
  98. </p>
  99. )}
  100. </div>
  101. );
  102. }
  103. return (
  104. <Modal size="lg" isOpen={isOpen} toggle={onClose} className="grw-create-page">
  105. <ModalHeader tag="h4" toggle={onClose} className={`bg-${deleteIconAndKey[deleteMode].color} text-light`}>
  106. <i className={`icon-fw icon-${deleteIconAndKey[deleteMode].icon}`}></i>
  107. { t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
  108. </ModalHeader>
  109. <ModalBody>
  110. <div className="form-group">
  111. <label>{ t('modal_delete.deleting_page') }:</label><br />
  112. <code>{ path }</code>
  113. </div>
  114. {renderDeleteRecursivelyForm()}
  115. {!isDeleteCompletelyModal && renderDeleteCompletelyForm()}
  116. </ModalBody>
  117. <ModalFooter>
  118. <ApiErrorMessageList errs={errs} />
  119. <button type="button" className={`btn btn-${deleteIconAndKey[deleteMode].color}`} onClick={deleteButtonHandler}>
  120. <i className={`icon-${deleteIconAndKey[deleteMode].icon}`} aria-hidden="true"></i>
  121. { t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
  122. </button>
  123. </ModalFooter>
  124. </Modal>
  125. );
  126. };
  127. PageDeleteModal.propTypes = {
  128. t: PropTypes.func.isRequired, // i18next
  129. isOpen: PropTypes.bool.isRequired,
  130. onClose: PropTypes.func.isRequired,
  131. pageId: PropTypes.string.isRequired,
  132. revisionId: PropTypes.string.isRequired,
  133. path: PropTypes.string.isRequired,
  134. isDeleteCompletelyModal: PropTypes.bool,
  135. isAbleToDeleteCompletely: PropTypes.bool,
  136. };
  137. PageDeleteModal.defaultProps = {
  138. isDeleteCompletelyModal: false,
  139. };
  140. export default withTranslation()(PageDeleteModal);