mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #9584 from overleaf/jel-copy-modal-wrapper
[web] Add wrapper for copy modal GitOrigin-RevId: 8291f953e418815797e8474a69de8f15c39af7b5
This commit is contained in:
parent
70e63ca0e3
commit
9cde88a9e8
5 changed files with 65 additions and 24 deletions
|
@ -9,16 +9,16 @@ import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
} from 'react-bootstrap'
|
} from 'react-bootstrap'
|
||||||
import { useProjectContext } from '../../../shared/context/project-context'
|
|
||||||
import { postJSON } from '../../../infrastructure/fetch-json'
|
import { postJSON } from '../../../infrastructure/fetch-json'
|
||||||
|
|
||||||
export default function CloneProjectModalContent({
|
export default function CloneProjectModalContent({
|
||||||
handleHide,
|
handleHide,
|
||||||
inFlight,
|
inFlight,
|
||||||
setInFlight,
|
setInFlight,
|
||||||
openProject,
|
handleAfterCloned,
|
||||||
|
projectId,
|
||||||
|
projectName,
|
||||||
}) {
|
}) {
|
||||||
const { _id: projectId, name: projectName } = useProjectContext()
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [error, setError] = useState()
|
const [error, setError] = useState()
|
||||||
|
@ -49,7 +49,7 @@ export default function CloneProjectModalContent({
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// open the cloned project
|
// open the cloned project
|
||||||
openProject(data.project_id)
|
handleAfterCloned(data)
|
||||||
})
|
})
|
||||||
.catch(({ response, data }) => {
|
.catch(({ response, data }) => {
|
||||||
if (response?.status === 400) {
|
if (response?.status === 400) {
|
||||||
|
@ -115,5 +115,7 @@ CloneProjectModalContent.propTypes = {
|
||||||
handleHide: PropTypes.func.isRequired,
|
handleHide: PropTypes.func.isRequired,
|
||||||
inFlight: PropTypes.bool,
|
inFlight: PropTypes.bool,
|
||||||
setInFlight: PropTypes.func.isRequired,
|
setInFlight: PropTypes.func.isRequired,
|
||||||
openProject: PropTypes.func.isRequired,
|
handleAfterCloned: PropTypes.func.isRequired,
|
||||||
|
projectId: PropTypes.string,
|
||||||
|
projectName: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { memo, useCallback, useState } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import CloneProjectModalContent from './clone-project-modal-content'
|
import CloneProjectModalContent from './clone-project-modal-content'
|
||||||
import AccessibleModal from '../../../shared/components/accessible-modal'
|
import AccessibleModal from '../../../shared/components/accessible-modal'
|
||||||
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
|
||||||
|
|
||||||
const CloneProjectModal = React.memo(function CloneProjectModal({
|
function CloneProjectModal({
|
||||||
show,
|
show,
|
||||||
handleHide,
|
handleHide,
|
||||||
openProject,
|
handleAfterCloned,
|
||||||
|
projectId,
|
||||||
|
projectName,
|
||||||
}) {
|
}) {
|
||||||
const [inFlight, setInFlight] = useState(false)
|
const [inFlight, setInFlight] = useState(false)
|
||||||
|
|
||||||
|
@ -29,16 +30,20 @@ const CloneProjectModal = React.memo(function CloneProjectModal({
|
||||||
handleHide={onHide}
|
handleHide={onHide}
|
||||||
inFlight={inFlight}
|
inFlight={inFlight}
|
||||||
setInFlight={setInFlight}
|
setInFlight={setInFlight}
|
||||||
openProject={openProject}
|
handleAfterCloned={handleAfterCloned}
|
||||||
|
projectId={projectId}
|
||||||
|
projectName={projectName}
|
||||||
/>
|
/>
|
||||||
</AccessibleModal>
|
</AccessibleModal>
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
|
|
||||||
CloneProjectModal.propTypes = {
|
CloneProjectModal.propTypes = {
|
||||||
handleHide: PropTypes.func.isRequired,
|
handleHide: PropTypes.func.isRequired,
|
||||||
show: PropTypes.bool.isRequired,
|
show: PropTypes.bool.isRequired,
|
||||||
openProject: PropTypes.func.isRequired,
|
handleAfterCloned: PropTypes.func.isRequired,
|
||||||
|
projectId: PropTypes.string,
|
||||||
|
projectName: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withErrorBoundary(CloneProjectModal)
|
export default memo(CloneProjectModal)
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { useProjectContext } from '../../../shared/context/project-context'
|
||||||
|
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
||||||
|
import CloneProjectModal from './clone-project-modal'
|
||||||
|
|
||||||
|
const EditorCloneProjectModalWrapper = React.memo(
|
||||||
|
function EditorCloneProjectModalWrapper({ show, handleHide, openProject }) {
|
||||||
|
const { _id: projectId, name: projectName } = useProjectContext()
|
||||||
|
|
||||||
|
if (!projectName) {
|
||||||
|
// wait for useProjectContext
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<CloneProjectModal
|
||||||
|
handleHide={handleHide}
|
||||||
|
show={show}
|
||||||
|
handleAfterCloned={openProject}
|
||||||
|
projectId={projectId}
|
||||||
|
projectName={projectName}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
EditorCloneProjectModalWrapper.propTypes = {
|
||||||
|
handleHide: PropTypes.func.isRequired,
|
||||||
|
show: PropTypes.bool.isRequired,
|
||||||
|
openProject: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withErrorBoundary(EditorCloneProjectModalWrapper)
|
|
@ -1,6 +1,6 @@
|
||||||
import App from '../../../base'
|
import App from '../../../base'
|
||||||
import { react2angular } from 'react2angular'
|
import { react2angular } from 'react2angular'
|
||||||
import CloneProjectModal from '../components/clone-project-modal'
|
import EditorCloneProjectModalWrapper from '../components/editor-clone-project-modal-wrapper'
|
||||||
import { rootContext } from '../../../shared/context/root-context'
|
import { rootContext } from '../../../shared/context/root-context'
|
||||||
|
|
||||||
export default App.controller(
|
export default App.controller(
|
||||||
|
@ -20,8 +20,8 @@ export default App.controller(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.openProject = projectId => {
|
$scope.openProject = project => {
|
||||||
window.location.assign(`/project/${projectId}`)
|
window.location.assign(`/project/${project.project_id}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -29,7 +29,7 @@ export default App.controller(
|
||||||
App.component(
|
App.component(
|
||||||
'cloneProjectModal',
|
'cloneProjectModal',
|
||||||
react2angular(
|
react2angular(
|
||||||
rootContext.use(CloneProjectModal),
|
rootContext.use(EditorCloneProjectModalWrapper),
|
||||||
Object.keys(CloneProjectModal.propTypes)
|
Object.keys(EditorCloneProjectModalWrapper.propTypes)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,10 +2,10 @@ import { fireEvent, screen, waitFor } from '@testing-library/react'
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
import fetchMock from 'fetch-mock'
|
import fetchMock from 'fetch-mock'
|
||||||
import CloneProjectModal from '../../../../../frontend/js/features/clone-project-modal/components/clone-project-modal'
|
import EditorCloneProjectModalWrapper from '../../../../../frontend/js/features/clone-project-modal/components/editor-clone-project-modal-wrapper'
|
||||||
import { renderWithEditorContext } from '../../../helpers/render-with-context'
|
import { renderWithEditorContext } from '../../../helpers/render-with-context'
|
||||||
|
|
||||||
describe('<CloneProjectModal />', function () {
|
describe('<EditorCloneProjectModalWrapper />', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
fetchMock.reset()
|
fetchMock.reset()
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,7 @@ describe('<CloneProjectModal />', function () {
|
||||||
const openProject = sinon.stub()
|
const openProject = sinon.stub()
|
||||||
|
|
||||||
renderWithEditorContext(
|
renderWithEditorContext(
|
||||||
<CloneProjectModal
|
<EditorCloneProjectModalWrapper
|
||||||
handleHide={handleHide}
|
handleHide={handleHide}
|
||||||
openProject={openProject}
|
openProject={openProject}
|
||||||
show
|
show
|
||||||
|
@ -49,7 +49,7 @@ describe('<CloneProjectModal />', function () {
|
||||||
const openProject = sinon.stub()
|
const openProject = sinon.stub()
|
||||||
|
|
||||||
renderWithEditorContext(
|
renderWithEditorContext(
|
||||||
<CloneProjectModal
|
<EditorCloneProjectModalWrapper
|
||||||
handleHide={handleHide}
|
handleHide={handleHide}
|
||||||
openProject={openProject}
|
openProject={openProject}
|
||||||
show
|
show
|
||||||
|
@ -112,7 +112,7 @@ describe('<CloneProjectModal />', function () {
|
||||||
const openProject = sinon.stub()
|
const openProject = sinon.stub()
|
||||||
|
|
||||||
renderWithEditorContext(
|
renderWithEditorContext(
|
||||||
<CloneProjectModal
|
<EditorCloneProjectModalWrapper
|
||||||
handleHide={handleHide}
|
handleHide={handleHide}
|
||||||
openProject={openProject}
|
openProject={openProject}
|
||||||
show
|
show
|
||||||
|
@ -149,7 +149,7 @@ describe('<CloneProjectModal />', function () {
|
||||||
const openProject = sinon.stub()
|
const openProject = sinon.stub()
|
||||||
|
|
||||||
renderWithEditorContext(
|
renderWithEditorContext(
|
||||||
<CloneProjectModal
|
<EditorCloneProjectModalWrapper
|
||||||
handleHide={handleHide}
|
handleHide={handleHide}
|
||||||
openProject={openProject}
|
openProject={openProject}
|
||||||
show
|
show
|
||||||
|
|
Loading…
Reference in a new issue