PageRenameModal.jsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 { withUnstatedContainers } from './UnstatedUtils';
  8. import AppContainer from '../services/AppContainer';
  9. import PageContainer from '../services/PageContainer';
  10. import ApiErrorMessage from './PageManagement/ApiErrorMessage';
  11. const PageRenameModal = (props) => {
  12. const {
  13. t, appContainer, pageContainer,
  14. } = props;
  15. const { path } = pageContainer.state;
  16. const { crowi } = appContainer.config;
  17. const [pageNameInput, setPageNameInput] = useState(path);
  18. const [errorCode, setErrorCode] = useState(null);
  19. const [errorMessage, setErrorMessage] = useState(null);
  20. const [isRenameRecursively, SetIsRenameRecursively] = useState(true);
  21. const [isRenameRedirect, SetIsRenameRedirect] = useState(false);
  22. const [isRenameMetadata, SetIsRenameMetadata] = useState(false);
  23. function changeIsRenameRecursivelyHandler() {
  24. SetIsRenameRecursively(!isRenameRecursively);
  25. }
  26. function changeIsRenameRedirectHandler() {
  27. SetIsRenameRedirect(!isRenameRedirect);
  28. }
  29. function changeIsRenameMetadataHandler() {
  30. SetIsRenameMetadata(!isRenameMetadata);
  31. }
  32. /**
  33. * change pageNameInput
  34. * @param {string} value
  35. */
  36. function inputChangeHandler(value) {
  37. setErrorCode(null);
  38. setErrorMessage(null);
  39. setPageNameInput(value);
  40. }
  41. async function rename() {
  42. try {
  43. setErrorCode(null);
  44. setErrorMessage(null);
  45. const response = await pageContainer.rename(
  46. pageNameInput,
  47. isRenameRecursively,
  48. isRenameRedirect,
  49. isRenameMetadata,
  50. );
  51. const { page } = response;
  52. const url = new URL(page.path, 'https://dummy');
  53. url.searchParams.append('renamedFrom', path);
  54. if (isRenameRedirect) {
  55. url.searchParams.append('withRedirect', true);
  56. }
  57. window.location.href = `${url.pathname}${url.search}`;
  58. }
  59. catch (err) {
  60. setErrorCode(err.code);
  61. setErrorMessage(err.message);
  62. }
  63. }
  64. return (
  65. <Modal size="lg" isOpen={props.isOpen} toggle={props.onClose} className="grw-create-page">
  66. <ModalHeader tag="h4" toggle={props.onClose} className="bg-primary text-light">
  67. { t('modal_rename.label.Move/Rename page') }
  68. </ModalHeader>
  69. <ModalBody>
  70. <div className="form-group">
  71. <label>{ t('modal_rename.label.Current page name') }</label><br />
  72. <code>{ path }</code>
  73. </div>
  74. <div className="form-group">
  75. <label htmlFor="newPageName">{ t('modal_rename.label.New page name') }</label><br />
  76. <div className="input-group">
  77. <div className="input-group-prepend">
  78. <span className="input-group-text">{crowi.url}</span>
  79. </div>
  80. <form className="flex-fill" onSubmit={(e) => { e.preventDefault(); rename() }}>
  81. <input
  82. type="text"
  83. value={pageNameInput}
  84. className="form-control"
  85. onChange={e => inputChangeHandler(e.target.value)}
  86. required
  87. />
  88. </form>
  89. </div>
  90. </div>
  91. <div className="custom-control custom-checkbox custom-checkbox-warning">
  92. <input
  93. className="custom-control-input"
  94. name="recursively"
  95. id="cbRenameRecursively"
  96. type="checkbox"
  97. checked={isRenameRecursively}
  98. onChange={changeIsRenameRecursivelyHandler}
  99. />
  100. <label className="custom-control-label" htmlFor="cbRenameRecursively">
  101. { t('modal_rename.label.Recursively') }
  102. <p className="form-text text-muted mt-0">{ t('modal_rename.help.recursive') }</p>
  103. </label>
  104. </div>
  105. <div className="custom-control custom-checkbox custom-checkbox-success">
  106. <input
  107. className="custom-control-input"
  108. name="create_redirect"
  109. id="cbRenameRedirect"
  110. type="checkbox"
  111. checked={isRenameRedirect}
  112. onChange={changeIsRenameRedirectHandler}
  113. />
  114. <label className="custom-control-label" htmlFor="cbRenameRedirect">
  115. { t('modal_rename.label.Redirect') }
  116. <p className="form-text text-muted mt-0">{ t('modal_rename.help.redirect') }</p>
  117. </label>
  118. </div>
  119. <div className="custom-control custom-checkbox custom-checkbox-primary">
  120. <input
  121. className="custom-control-input"
  122. name="remain_metadata"
  123. id="cbRenameMetadata"
  124. type="checkbox"
  125. checked={isRenameMetadata}
  126. onChange={changeIsRenameMetadataHandler}
  127. />
  128. <label className="custom-control-label" htmlFor="cbRenameMetadata">
  129. { t('modal_rename.label.Do not update metadata') }
  130. <p className="form-text text-muted mt-0">{ t('modal_rename.help.metadata') }</p>
  131. </label>
  132. </div>
  133. </ModalBody>
  134. <ModalFooter>
  135. <ApiErrorMessage errorCode={errorCode} errorMessage={errorMessage} targetPath={pageNameInput} />
  136. <button type="button" className="btn btn-primary" onClick={rename}>Rename</button>
  137. </ModalFooter>
  138. </Modal>
  139. );
  140. };
  141. /**
  142. * Wrapper component for using unstated
  143. */
  144. const PageRenameModalWrapper = withUnstatedContainers(PageRenameModal, [AppContainer, PageContainer]);
  145. PageRenameModal.propTypes = {
  146. t: PropTypes.func.isRequired, // i18next
  147. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  148. pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  149. isOpen: PropTypes.bool.isRequired,
  150. onClose: PropTypes.func.isRequired,
  151. path: PropTypes.string.isRequired,
  152. };
  153. export default withTranslation()(PageRenameModalWrapper);