|
|
@@ -1,5 +1,6 @@
|
|
|
import PropTypes from 'prop-types'
|
|
|
-import { Trans } from 'react-i18next'
|
|
|
+import { useMemo, useState } from 'react'
|
|
|
+import { useTranslation } from 'react-i18next'
|
|
|
import {
|
|
|
Modal,
|
|
|
Alert,
|
|
|
@@ -8,37 +9,70 @@ import {
|
|
|
FormControl,
|
|
|
FormGroup,
|
|
|
} from 'react-bootstrap'
|
|
|
-import AccessibleModal from '../../../shared/components/accessible-modal'
|
|
|
+import { useProjectContext } from '../../../shared/context/project-context'
|
|
|
+import { postJSON } from '../../../infrastructure/fetch-json'
|
|
|
|
|
|
export default function CloneProjectModalContent({
|
|
|
- animation = true,
|
|
|
- show,
|
|
|
- cancel,
|
|
|
- handleSubmit,
|
|
|
- clonedProjectName,
|
|
|
- setClonedProjectName,
|
|
|
- error,
|
|
|
+ handleHide,
|
|
|
inFlight,
|
|
|
- valid,
|
|
|
+ setInFlight,
|
|
|
+ openProject,
|
|
|
}) {
|
|
|
+ const { _id: projectId, name: projectName } = useProjectContext()
|
|
|
+ const { t } = useTranslation()
|
|
|
+
|
|
|
+ const [error, setError] = useState()
|
|
|
+ const [clonedProjectName, setClonedProjectName] = useState(
|
|
|
+ `${projectName} (Copy)`
|
|
|
+ )
|
|
|
+
|
|
|
+ // valid if the cloned project has a name
|
|
|
+ const valid = useMemo(() => clonedProjectName.trim().length > 0, [
|
|
|
+ clonedProjectName,
|
|
|
+ ])
|
|
|
+
|
|
|
+ // form submission: clone the project if the name is valid
|
|
|
+ const handleSubmit = event => {
|
|
|
+ event.preventDefault()
|
|
|
+
|
|
|
+ if (!valid) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ setError(false)
|
|
|
+ setInFlight(true)
|
|
|
+
|
|
|
+ // clone the project
|
|
|
+ postJSON(`/project/${projectId}/clone`, {
|
|
|
+ body: { projectName: clonedProjectName },
|
|
|
+ })
|
|
|
+ .then(data => {
|
|
|
+ // open the cloned project
|
|
|
+ openProject(data.project_id)
|
|
|
+ })
|
|
|
+ .catch(({ response, data }) => {
|
|
|
+ if (response?.status === 400) {
|
|
|
+ setError(data.message)
|
|
|
+ } else {
|
|
|
+ setError(true)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ setInFlight(false)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
return (
|
|
|
- <AccessibleModal
|
|
|
- animation={animation}
|
|
|
- show={show}
|
|
|
- onHide={cancel}
|
|
|
- id="clone-project-modal"
|
|
|
- >
|
|
|
+ <>
|
|
|
<Modal.Header closeButton>
|
|
|
- <Modal.Title>
|
|
|
- <Trans i18nKey="copy_project" />
|
|
|
- </Modal.Title>
|
|
|
+ <Modal.Title>{t('copy_project')}</Modal.Title>
|
|
|
</Modal.Header>
|
|
|
|
|
|
<Modal.Body>
|
|
|
<form id="clone-project-form" onSubmit={handleSubmit}>
|
|
|
<FormGroup>
|
|
|
<ControlLabel htmlFor="clone-project-form-name">
|
|
|
- <Trans i18nKey="new_name" />
|
|
|
+ {t('new_name')}
|
|
|
</ControlLabel>
|
|
|
|
|
|
<FormControl
|
|
|
@@ -54,18 +88,14 @@ export default function CloneProjectModalContent({
|
|
|
|
|
|
{error && (
|
|
|
<Alert bsStyle="danger">
|
|
|
- {error.length ? (
|
|
|
- error
|
|
|
- ) : (
|
|
|
- <Trans i18nKey="generic_something_went_wrong" />
|
|
|
- )}
|
|
|
+ {error.length ? error : t('generic_something_went_wrong')}
|
|
|
</Alert>
|
|
|
)}
|
|
|
</Modal.Body>
|
|
|
|
|
|
<Modal.Footer>
|
|
|
- <Button type="button" disabled={inFlight} onClick={cancel}>
|
|
|
- <Trans i18nKey="cancel" />
|
|
|
+ <Button type="button" disabled={inFlight} onClick={handleHide}>
|
|
|
+ {t('cancel')}
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
@@ -74,26 +104,15 @@ export default function CloneProjectModalContent({
|
|
|
bsStyle="primary"
|
|
|
disabled={inFlight || !valid}
|
|
|
>
|
|
|
- {inFlight ? (
|
|
|
- <>
|
|
|
- <Trans i18nKey="copying" />…
|
|
|
- </>
|
|
|
- ) : (
|
|
|
- <Trans i18nKey="copy" />
|
|
|
- )}
|
|
|
+ {inFlight ? <>{t('copying')}…</> : t('copy')}
|
|
|
</Button>
|
|
|
</Modal.Footer>
|
|
|
- </AccessibleModal>
|
|
|
+ </>
|
|
|
)
|
|
|
}
|
|
|
CloneProjectModalContent.propTypes = {
|
|
|
- animation: PropTypes.bool,
|
|
|
- show: PropTypes.bool.isRequired,
|
|
|
- cancel: PropTypes.func.isRequired,
|
|
|
- handleSubmit: PropTypes.func.isRequired,
|
|
|
- clonedProjectName: PropTypes.string,
|
|
|
- setClonedProjectName: PropTypes.func.isRequired,
|
|
|
- error: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
|
|
|
- inFlight: PropTypes.bool.isRequired,
|
|
|
- valid: PropTypes.bool.isRequired,
|
|
|
+ handleHide: PropTypes.func.isRequired,
|
|
|
+ inFlight: PropTypes.bool,
|
|
|
+ setInFlight: PropTypes.func.isRequired,
|
|
|
+ openProject: PropTypes.func.isRequired,
|
|
|
}
|