clone-project-modal-content.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* eslint-disable jsx-a11y/no-autofocus */
  2. import PropTypes from 'prop-types'
  3. import { useMemo, useState } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import {
  6. Modal,
  7. Alert,
  8. Button,
  9. ControlLabel,
  10. FormControl,
  11. FormGroup,
  12. } from 'react-bootstrap'
  13. import { postJSON } from '../../../infrastructure/fetch-json'
  14. export default function CloneProjectModalContent({
  15. handleHide,
  16. inFlight,
  17. setInFlight,
  18. handleAfterCloned,
  19. projectId,
  20. projectName,
  21. }) {
  22. const { t } = useTranslation()
  23. const [error, setError] = useState()
  24. const [clonedProjectName, setClonedProjectName] = useState(
  25. `${projectName} (Copy)`
  26. )
  27. // valid if the cloned project has a name
  28. const valid = useMemo(
  29. () => clonedProjectName.trim().length > 0,
  30. [clonedProjectName]
  31. )
  32. // form submission: clone the project if the name is valid
  33. const handleSubmit = event => {
  34. event.preventDefault()
  35. if (!valid) {
  36. return
  37. }
  38. setError(false)
  39. setInFlight(true)
  40. // clone the project
  41. postJSON(`/project/${projectId}/clone`, {
  42. body: { projectName: clonedProjectName },
  43. })
  44. .then(data => {
  45. // open the cloned project
  46. handleAfterCloned(data)
  47. })
  48. .catch(({ response, data }) => {
  49. if (response?.status === 400) {
  50. setError(data.message)
  51. } else {
  52. setError(true)
  53. }
  54. })
  55. .finally(() => {
  56. setInFlight(false)
  57. })
  58. }
  59. return (
  60. <>
  61. <Modal.Header closeButton>
  62. <Modal.Title>{t('copy_project')}</Modal.Title>
  63. </Modal.Header>
  64. <Modal.Body>
  65. <form id="clone-project-form" onSubmit={handleSubmit}>
  66. <FormGroup>
  67. <ControlLabel htmlFor="clone-project-form-name">
  68. {t('new_name')}
  69. </ControlLabel>
  70. <FormControl
  71. id="clone-project-form-name"
  72. type="text"
  73. placeholder="New Project Name"
  74. required
  75. value={clonedProjectName}
  76. onChange={event => setClonedProjectName(event.target.value)}
  77. autoFocus
  78. />
  79. </FormGroup>
  80. </form>
  81. {error && (
  82. <Alert bsStyle="danger">
  83. {error.length ? error : t('generic_something_went_wrong')}
  84. </Alert>
  85. )}
  86. </Modal.Body>
  87. <Modal.Footer>
  88. <Button type="button" disabled={inFlight} onClick={handleHide}>
  89. {t('cancel')}
  90. </Button>
  91. <Button
  92. form="clone-project-form"
  93. type="submit"
  94. bsStyle="primary"
  95. disabled={inFlight || !valid}
  96. >
  97. {inFlight ? <>{t('copying')}…</> : t('copy')}
  98. </Button>
  99. </Modal.Footer>
  100. </>
  101. )
  102. }
  103. CloneProjectModalContent.propTypes = {
  104. handleHide: PropTypes.func.isRequired,
  105. inFlight: PropTypes.bool,
  106. setInFlight: PropTypes.func.isRequired,
  107. handleAfterCloned: PropTypes.func.isRequired,
  108. projectId: PropTypes.string,
  109. projectName: PropTypes.string,
  110. }