Procházet zdrojové kódy

Merge pull request #27316 from overleaf/dp-file-menu-options

Add copy and submit project options to new editor file menu

GitOrigin-RevId: 7f402d96f278f2b084375441089b286adaa731b8
David před 1 rokem
rodič
revize
975d1ee250

+ 13 - 3
services/web/frontend/js/features/clone-project-modal/components/editor-clone-project-modal-wrapper.tsx

@@ -1,8 +1,12 @@
-import React from 'react'
+import React, { useCallback } from 'react'
 import { useProjectContext } from '../../../shared/context/project-context'
 import withErrorBoundary from '../../../infrastructure/error-boundary'
 import CloneProjectModal from './clone-project-modal'
 
+type ProjectCopyResponse = {
+  project_id: string
+}
+
 const EditorCloneProjectModalWrapper = React.memo(
   function EditorCloneProjectModalWrapper({
     show,
@@ -11,9 +15,15 @@ const EditorCloneProjectModalWrapper = React.memo(
   }: {
     show: boolean
     handleHide: () => void
-    openProject: ({ project_id }: { project_id: string }) => void
+    openProject: (projectId: string) => void
   }) {
     const { project, tags: projectTags } = useProjectContext()
+    const handleAfterCloned = useCallback(
+      ({ project_id: projectId }: ProjectCopyResponse) => {
+        openProject(projectId)
+      },
+      [openProject]
+    )
 
     if (!project) {
       // wait for useProjectContext
@@ -23,7 +33,7 @@ const EditorCloneProjectModalWrapper = React.memo(
         <CloneProjectModal
           handleHide={handleHide}
           show={show}
-          handleAfterCloned={openProject}
+          handleAfterCloned={handleAfterCloned}
           projectId={project._id}
           projectName={project.name}
           projectTags={projectTags}

+ 2 - 13
services/web/frontend/js/features/editor-left-menu/components/actions-copy-project.tsx

@@ -2,24 +2,13 @@ import { useCallback, useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import EditorCloneProjectModalWrapper from '../../clone-project-modal/components/editor-clone-project-modal-wrapper'
 import LeftMenuButton from './left-menu-button'
-import { useLocation } from '../../../shared/hooks/use-location'
 import * as eventTracking from '../../../infrastructure/event-tracking'
-
-type ProjectCopyResponse = {
-  project_id: string
-}
+import useOpenProject from '@/shared/hooks/use-open-project'
 
 export default function ActionsCopyProject() {
   const [showModal, setShowModal] = useState(false)
   const { t } = useTranslation()
-  const location = useLocation()
-
-  const openProject = useCallback(
-    ({ project_id: projectId }: ProjectCopyResponse) => {
-      location.assign(`/project/${projectId}`)
-    },
-    [location]
-  )
+  const openProject = useOpenProject()
 
   const handleShowModal = useCallback(() => {
     eventTracking.sendMB('left-menu-copy')

+ 2 - 13
services/web/frontend/js/features/ide-redesign/components/toolbar/duplicate-project.tsx

@@ -1,28 +1,17 @@
 import EditorCloneProjectModalWrapper from '@/features/clone-project-modal/components/editor-clone-project-modal-wrapper'
 import OLDropdownMenuItem from '@/shared/components/ol/ol-dropdown-menu-item'
 import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
-import { useLocation } from '@/shared/hooks/use-location'
+import useOpenProject from '@/shared/hooks/use-open-project'
 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 openProject = useOpenProject()
 
   const handleShowModal = useCallback(() => {
     sendEvent('copy-project', { location: 'project-title-dropdown' })

+ 24 - 2
services/web/frontend/js/features/ide-redesign/components/toolbar/menu-bar.tsx

@@ -27,6 +27,9 @@ import { useDetachCompileContext as useCompileContext } from '@/shared/context/d
 import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
 import { useProjectSettingsContext } from '@/features/editor-left-menu/context/project-settings-context'
 import { useSurveyUrl } from '../../hooks/use-survey-url'
+import getMeta from '@/utils/meta'
+import EditorCloneProjectModalWrapper from '@/features/clone-project-modal/components/editor-clone-project-modal-wrapper'
+import useOpenProject from '@/shared/hooks/use-open-project'
 
 export const ToolbarMenuBar = () => {
   const { t } = useTranslation()
@@ -38,6 +41,10 @@ export const ToolbarMenuBar = () => {
   const { pdfUrl } = useCompileContext()
   const wordCountEnabled = pdfUrl || isSplitTestEnabled('word-count-client')
   const [showWordCountModal, setShowWordCountModal] = useState(false)
+  const [showCloneProjectModal, setShowCloneProjectModal] = useState(false)
+  const openProject = useOpenProject()
+
+  const anonymous = getMeta('ol-anonymous')
 
   useCommandProvider(
     () => [
@@ -58,16 +65,26 @@ export const ToolbarMenuBar = () => {
         },
         id: 'word_count',
       },
+      {
+        type: 'command',
+        label: t('make_a_copy'),
+        disabled: anonymous,
+        handler: () => {
+          setShowCloneProjectModal(true)
+        },
+        id: 'copy_project',
+      },
     ],
-    [t, setView, view, wordCountEnabled]
+    [t, setView, view, wordCountEnabled, anonymous]
   )
   const fileMenuStructure: MenuStructure = useMemo(
     () => [
       {
         id: 'file-file-tree',
-        children: ['new_file', 'new_folder', 'upload_file'],
+        children: ['new_file', 'new_folder', 'upload_file', 'copy_project'],
       },
       { id: 'file-tools', children: ['show_version_history', 'word_count'] },
+      { id: 'submit', children: ['submit-project'] },
       {
         id: 'file-download',
         children: ['download-as-source-zip', 'download-pdf'],
@@ -286,6 +303,11 @@ export const ToolbarMenuBar = () => {
         show={showWordCountModal}
         handleHide={() => setShowWordCountModal(false)}
       />
+      <EditorCloneProjectModalWrapper
+        show={showCloneProjectModal}
+        handleHide={() => setShowCloneProjectModal(false)}
+        openProject={openProject}
+      />
     </>
   )
 }

+ 15 - 0
services/web/frontend/js/shared/hooks/use-open-project.ts

@@ -0,0 +1,15 @@
+import { useCallback } from 'react'
+import { useLocation } from './use-location'
+
+export default function useOpenProject() {
+  const location = useLocation()
+
+  const openProject = useCallback(
+    (projectId: string) => {
+      location.assign(`/project/${projectId}`)
+    },
+    [location]
+  )
+
+  return openProject
+}