From 1b15dc38542ec7b1a6e4fea7515200c016367f22 Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Mon, 2 Jun 2025 11:30:25 +0100 Subject: [PATCH] Merge pull request #26003 from overleaf/mj-ide-duplicate-project [web] Editor redesign: Add project duplication button GitOrigin-RevId: 93e5aa66a7ccc13650e07fda041394811874dafa --- .../components/toolbar/duplicate-project.tsx | 48 +++++++++++++++++++ .../components/toolbar/project-title.tsx | 2 + 2 files changed, 50 insertions(+) create mode 100644 services/web/frontend/js/features/ide-redesign/components/toolbar/duplicate-project.tsx diff --git a/services/web/frontend/js/features/ide-redesign/components/toolbar/duplicate-project.tsx b/services/web/frontend/js/features/ide-redesign/components/toolbar/duplicate-project.tsx new file mode 100644 index 0000000000..74f868cc91 --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/toolbar/duplicate-project.tsx @@ -0,0 +1,48 @@ +import EditorCloneProjectModalWrapper from '@/features/clone-project-modal/components/editor-clone-project-modal-wrapper' +import OLDropdownMenuItem from '@/features/ui/components/ol/ol-dropdown-menu-item' +import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics' +import { useLocation } from '@/shared/hooks/use-location' +import getMeta from '@/utils/meta' +import { useCallback, useState } from 'react' +import { useTranslation } from 'react-i18next' + +type ProjectCopyResponse = { + project_id: string +} + +export const DuplicateProject = () => { + const { sendEvent } = useEditorAnalytics() + const { t } = useTranslation() + const [showModal, setShowModal] = useState(false) + const location = useLocation() + const anonymous = getMeta('ol-anonymous') + + const openProject = useCallback( + ({ project_id: projectId }: ProjectCopyResponse) => { + location.assign(`/project/${projectId}`) + }, + [location] + ) + + const handleShowModal = useCallback(() => { + sendEvent('copy-project', { location: 'project-title-dropdown' }) + setShowModal(true) + }, [sendEvent]) + + if (anonymous) { + return null + } + + return ( + <> + + {t('copy')} + + setShowModal(false)} + openProject={openProject} + /> + + ) +} diff --git a/services/web/frontend/js/features/ide-redesign/components/toolbar/project-title.tsx b/services/web/frontend/js/features/ide-redesign/components/toolbar/project-title.tsx index 68860da4ea..61e29023a0 100644 --- a/services/web/frontend/js/features/ide-redesign/components/toolbar/project-title.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/toolbar/project-title.tsx @@ -13,6 +13,7 @@ import { DownloadProjectPDF, DownloadProjectZip } from './download-project' import { useCallback, useState } from 'react' import OLDropdownMenuItem from '@/features/ui/components/ol/ol-dropdown-menu-item' import EditableLabel from './editable-label' +import { DuplicateProject } from './duplicate-project' const [publishModalModules] = importOverleafModules('publishModal') const SubmitProjectButton = publishModalModules?.import.NewPublishToolbarButton @@ -73,6 +74,7 @@ export const ToolbarProjectTitle = () => { + { setIsRenaming(true)