ソースを参照

Only show the Rename option for a project owned by the current user (#15346)

GitOrigin-RevId: 439ba2c69aa1e3d9cd326f2b501467f6d9cca798
Alf Eaton 3 年 前
親
コミット
c2c86ff794

+ 10 - 2
services/web/frontend/js/features/project-list/components/project-list-root.tsx

@@ -31,13 +31,21 @@ import { GenericErrorBoundaryFallback } from '../../../shared/components/generic
 function ProjectListRoot() {
   const { isReady } = useWaitForI18n()
 
-  return isReady ? (
+  if (!isReady) {
+    return null
+  }
+
+  return <ProjectListRootInner />
+}
+
+export function ProjectListRootInner() {
+  return (
     <ProjectListProvider>
       <ColorPickerProvider>
         <ProjectListPageContent />
       </ColorPickerProvider>
     </ProjectListProvider>
-  ) : null
+  )
 }
 
 function ProjectListPageContent() {

+ 11 - 2
services/web/frontend/js/features/project-list/components/table/project-tools/menu-items/rename-project-menu-item.tsx

@@ -21,7 +21,16 @@ function RenameProjectMenuItem() {
     }
   }, [isMounted])
 
-  if (selectedProjects.length !== 1) return null
+  if (selectedProjects.length !== 1) {
+    return null
+  }
+
+  const [selectedProject] = selectedProjects
+
+  // only show Rename if the current user is the project owner
+  if (selectedProject.accessLevel !== 'owner') {
+    return null
+  }
 
   return (
     <>
@@ -29,7 +38,7 @@ function RenameProjectMenuItem() {
       <RenameProjectModal
         handleCloseModal={handleCloseModal}
         showModal={showModal}
-        project={selectedProjects[0]}
+        project={selectedProject}
       />
     </>
   )

+ 77 - 0
services/web/test/frontend/features/project-list/components/table/project-tools/project-tools-rename.test.tsx

@@ -0,0 +1,77 @@
+import { render, screen, within } from '@testing-library/react'
+import { expect } from 'chai'
+import moment from 'moment/moment'
+import fetchMock from 'fetch-mock'
+import { Project } from '../../../../../../../types/project/dashboard/api'
+import { ProjectListRootInner } from '@/features/project-list/components/project-list-root'
+
+const users = {
+  picard: {
+    id: '62d6d0b4c5c5030a4d696c7a',
+    email: 'picard@overleaf.com',
+    firstName: 'Jean-Luc',
+    lastName: 'Picard',
+  },
+  riker: {
+    id: '624333f147cfd8002622a1d3',
+    email: 'riker@overleaf.com',
+    firstName: 'William',
+    lastName: 'Riker',
+  },
+}
+
+const projects: Project[] = [
+  {
+    id: '62f17f594641b405ca2b3264',
+    name: 'Starfleet Report (owner)',
+    lastUpdated: moment().subtract(1, 'day').toISOString(),
+    lastUpdatedBy: users.riker,
+    accessLevel: 'owner',
+    source: 'owner',
+    archived: false,
+    trashed: false,
+    owner: users.picard,
+  },
+  {
+    id: '62f17f594641b405ca2b3265',
+    name: 'Starfleet Report (readAndWrite)',
+    lastUpdated: moment().subtract(1, 'day').toISOString(),
+    lastUpdatedBy: users.picard,
+    accessLevel: 'readAndWrite',
+    source: 'owner',
+    archived: false,
+    trashed: false,
+    owner: users.riker,
+  },
+]
+
+describe('<ProjectTools />', function () {
+  beforeEach(function () {
+    window.metaAttributesCache.set('ol-ExposedSettings', {})
+    window.metaAttributesCache.set('ol-prefetchedProjectsBlob', {
+      projects,
+      totalSize: 100,
+    })
+    fetchMock.get('/system/messages', [])
+  })
+
+  afterEach(function () {
+    window.metaAttributesCache.clear()
+    fetchMock.reset()
+  })
+
+  it('does not show the Rename option for a project owned by a different user', function () {
+    render(<ProjectListRootInner />)
+    screen.getByLabelText('Select Starfleet Report (readAndWrite)').click()
+    screen.getByRole('button', { name: 'More' }).click()
+    expect(screen.queryByRole('menuitem', { name: 'Rename' })).to.be.null
+  })
+
+  it('displays the Rename option for a project owned by the current user', function () {
+    render(<ProjectListRootInner />)
+    screen.getByLabelText('Select Starfleet Report (owner)').click()
+    screen.getByRole('button', { name: 'More' }).click()
+    screen.getByRole('menuitem', { name: 'Rename' }).click()
+    within(screen.getByRole('dialog')).getByText('Rename Project')
+  })
+})