clone-project-modal-content.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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(
  28. () => clonedProjectName.trim().length > 0,
  29. [clonedProjectName]
  30. )
  31. // form submission: clone the project if the name is valid
  32. const handleSubmit = event => {
  33. event.preventDefault()
  34. if (!valid) {
  35. return
  36. }
  37. setError(false)
  38. setInFlight(true)
  39. // clone the project
  40. postJSON(`/project/${projectId}/clone`, {
  41. body: { projectName: clonedProjectName },
  42. })
  43. .then(data => {
  44. // open the cloned project
  45. openProject(data.project_id)
  46. })
  47. .catch(({ response, data }) => {
  48. if (response?.status === 400) {
  49. setError(data.message)
  50. } else {
  51. setError(true)
  52. }
  53. })
  54. .finally(() => {
  55. setInFlight(false)
  56. })
  57. }
  58. return (
  59. <>
  60. <Modal.Header closeButton>
  61. <Modal.Title>{t('copy_project')}</Modal.Title>
  62. </Modal.Header>
  63. <Modal.Body>
  64. <form id="clone-project-form" onSubmit={handleSubmit}>
  65. <FormGroup>
  66. <ControlLabel htmlFor="clone-project-form-name">
  67. {t('new_name')}
  68. </ControlLabel>
  69. <FormControl
  70. id="clone-project-form-name"
  71. type="text"
  72. placeholder="New Project Name"
  73. required
  74. value={clonedProjectName}
  75. onChange={event => setClonedProjectName(event.target.value)}
  76. />
  77. </FormGroup>
  78. </form>
  79. {error && (
  80. <Alert bsStyle="danger">
  81. {error.length ? error : t('generic_something_went_wrong')}
  82. </Alert>
  83. )}
  84. </Modal.Body>
  85. <Modal.Footer>
  86. <Button type="button" disabled={inFlight} onClick={handleHide}>
  87. {t('cancel')}
  88. </Button>
  89. <Button
  90. form="clone-project-form"
  91. type="submit"
  92. bsStyle="primary"
  93. disabled={inFlight || !valid}
  94. >
  95. {inFlight ? <>{t('copying')}…</> : t('copy')}
  96. </Button>
  97. </Modal.Footer>
  98. </>
  99. )
  100. }
  101. CloneProjectModalContent.propTypes = {
  102. handleHide: PropTypes.func.isRequired,
  103. inFlight: PropTypes.bool,
  104. setInFlight: PropTypes.func.isRequired,
  105. openProject: PropTypes.func.isRequired,
  106. }