clone-project-modal-content.js 2.9 KB

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