Просмотр исходного кода

Merge pull request #4069 from overleaf/as-file-views-use-context

Pull project id from `EditorContext` instead of `window` in file views

GitOrigin-RevId: 78c2686d8bcd1e95414631ca77143fd9ae3edbc6
Jakob Ackermann 5 лет назад
Родитель
Сommit
8f0a0439cd

+ 14 - 9
services/web/frontend/js/features/binary-file/components/binary-file-header.js

@@ -1,12 +1,14 @@
 import React, { useState, useCallback } from 'react'
 import PropTypes from 'prop-types'
+import { Trans, useTranslation } from 'react-i18next'
+
 import Icon from '../../../shared/components/icon'
 import { formatTime, relativeDate } from '../../utils/format-date'
-import { Trans, useTranslation } from 'react-i18next'
-import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
 import { postJSON } from '../../../infrastructure/fetch-json'
 import useIsMounted from '../../../shared/hooks/use-is-mounted'
+import { useEditorContext } from '../../../shared/context/editor-context'
 
+import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
 const tprLinkedFileInfo = importOverleafModules('tprLinkedFileInfo')
 const tprLinkedFileRefreshError = importOverleafModules(
   'tprLinkedFileRefreshError'
@@ -30,12 +32,15 @@ function shortenedUrl(url) {
 }
 
 export default function BinaryFileHeader({ file, storeReferencesKeys }) {
-  const [refreshing, setRefreshing] = useState(false)
-  const [refreshError, setRefreshError] = useState(null)
+  const { projectId } = useEditorContext({
+    projectId: PropTypes.string.isRequired,
+  })
   const { t } = useTranslation()
-
   const isMounted = useIsMounted()
 
+  const [refreshing, setRefreshing] = useState(false)
+  const [refreshError, setRefreshError] = useState(null)
+
   let fileInfo
   if (file.linkedFileData) {
     if (file.linkedFileData.provider === 'url') {
@@ -63,7 +68,7 @@ export default function BinaryFileHeader({ file, storeReferencesKeys }) {
     setRefreshing(true)
     // Replacement of the file handled by the file tree
     window.expectingLinkedFileRefreshedSocketFor = file.name
-    postJSON(`/project/${window.project_id}/linked_file/${file.id}/refresh`)
+    postJSON(`/project/${projectId}/linked_file/${file.id}/refresh`)
       .then(() => {
         if (isMounted.current) {
           setRefreshing(false)
@@ -90,7 +95,7 @@ export default function BinaryFileHeader({ file, storeReferencesKeys }) {
         body: { shouldBroadcast: true },
       }
 
-      postJSON(`/project/${window.project_id}/references/indexAll`, opts)
+      postJSON(`/project/${projectId}/references/indexAll`, opts)
         .then(response => {
           // Later updated by the socket but also updated here for immediate use
           storeReferencesKeys(response.keys)
@@ -99,7 +104,7 @@ export default function BinaryFileHeader({ file, storeReferencesKeys }) {
           console.log(error)
         })
     }
-  }, [file, isMounted, storeReferencesKeys])
+  }, [file, projectId, isMounted, storeReferencesKeys])
 
   return (
     <div className="binary-file-header">
@@ -120,7 +125,7 @@ export default function BinaryFileHeader({ file, storeReferencesKeys }) {
       )}
       &nbsp;
       <a
-        href={`/project/${window.project_id}/file/${file.id}`}
+        href={`/project/${projectId}/file/${file.id}`}
         className="btn btn-info"
       >
         <Icon type="download" modifier="fw" />

+ 6 - 1
services/web/frontend/js/features/binary-file/components/binary-file-image.js

@@ -1,10 +1,15 @@
 import React from 'react'
 import PropTypes from 'prop-types'
+import { useEditorContext } from '../../../shared/context/editor-context'
 
 export default function BinaryFileImage({ fileName, fileId, onLoad, onError }) {
+  const { projectId } = useEditorContext({
+    projectId: PropTypes.string.isRequired,
+  })
+
   return (
     <img
-      src={`/project/${window.project_id}/file/${fileId}`}
+      src={`/project/${projectId}/file/${fileId}`}
       onLoad={onLoad}
       onError={onError}
       onAbort={onError}

+ 7 - 2
services/web/frontend/js/features/binary-file/components/binary-file-text.js

@@ -1,14 +1,19 @@
 import React, { useState, useEffect } from 'react'
 import PropTypes from 'prop-types'
+import { useEditorContext } from '../../../shared/context/editor-context'
 
 const MAX_FILE_SIZE = 2 * 1024 * 1024
 
 export default function BinaryFileText({ file, onLoad, onError }) {
+  const { projectId } = useEditorContext({
+    projectId: PropTypes.string.isRequired,
+  })
+
   const [textPreview, setTextPreview] = useState('')
   const [shouldShowDots, setShouldShowDots] = useState(false)
 
   useEffect(() => {
-    let path = `/project/${window.project_id}/file/${file.id}`
+    let path = `/project/${projectId}/file/${file.id}`
     fetch(path, { method: 'HEAD' })
       .then(response => {
         if (!response.ok) throw new Error('HTTP Error Code: ' + response.status)
@@ -45,7 +50,7 @@ export default function BinaryFileText({ file, onLoad, onError }) {
       .catch(err => {
         onError()
       })
-  }, [file.id, onError, onLoad])
+  }, [projectId, file.id, onError, onLoad])
   return (
     <div>
       {textPreview && (

+ 2 - 1
services/web/frontend/js/features/binary-file/controllers/binary-file-controller.js

@@ -2,6 +2,7 @@ import App from '../../../base'
 import { react2angular } from 'react2angular'
 import _ from 'lodash'
 
+import { rootContext } from '../../../shared/context/root-context'
 import BinaryFile from '../components/binary-file'
 
 export default App.controller(
@@ -18,5 +19,5 @@ export default App.controller(
 
 App.component(
   'binaryFile',
-  react2angular(BinaryFile, ['storeReferencesKeys', 'file'])
+  react2angular(rootContext.use(BinaryFile), ['storeReferencesKeys', 'file'])
 )

+ 5 - 6
services/web/frontend/stories/binary-file.stories.js

@@ -1,10 +1,9 @@
 import React from 'react'
 
+import { ContextRoot } from '../js/shared/context/root-context'
 import BinaryFile from '../js/features/binary-file/components/binary-file'
 import useFetchMock from './hooks/use-fetch-mock'
 
-window.project_id = 'proj123'
-
 const setupFetchMock = fetchMock => {
   fetchMock
     .head('express:/project/:project_id/file/:file_id', {
@@ -20,12 +19,10 @@ const setupFetchMock = fetchMock => {
     })
 }
 
-window.project_id = '1234'
-
 const fileData = {
   id: 'file-id',
   name: 'file.tex',
-  created: new Date(),
+  created: new Date().toISOString(),
 }
 
 export const FileFromUrl = args => {
@@ -181,7 +178,9 @@ export default {
     Story => (
       <>
         <style>{'html, body { height: 100%; }'}</style>
-        <Story />
+        <ContextRoot ide={window._ide} settings={{}}>
+          <Story />
+        </ContextRoot>
       </>
     ),
   ],

+ 17 - 24
services/web/test/frontend/features/binary-file/components/binary-file-header.test.js

@@ -1,6 +1,5 @@
 import React from 'react'
 import {
-  render,
   screen,
   fireEvent,
   waitForElementToBeRemoved,
@@ -9,6 +8,7 @@ import { expect } from 'chai'
 import fetchMock from 'fetch-mock'
 import sinon from 'sinon'
 
+import { renderWithEditorContext } from '../../../helpers/render-with-context'
 import BinaryFileHeader from '../../../../../frontend/js/features/binary-file/components/binary-file-header.js'
 
 describe('<BinaryFileHeader/>', function () {
@@ -50,16 +50,15 @@ describe('<BinaryFileHeader/>', function () {
     created: new Date(2021, 1, 17, 3, 24).toISOString(),
   }
 
-  let storeReferencesKeys
-
   beforeEach(function () {
     fetchMock.reset()
-    storeReferencesKeys = sinon.stub()
   })
 
   describe('header text', function () {
     it('Renders the correct text for a file with the url provider', function () {
-      render(<BinaryFileHeader file={urlFile} storeReferencesKeys={() => {}} />)
+      renderWithEditorContext(
+        <BinaryFileHeader file={urlFile} storeReferencesKeys={() => {}} />
+      )
       screen.getByText('Imported from', { exact: false })
       screen.getByText('at 3:24 am Wed, 17th Feb 21', {
         exact: false,
@@ -67,7 +66,7 @@ describe('<BinaryFileHeader/>', function () {
     })
 
     it('Renders the correct text for a file with the project_file provider', function () {
-      render(
+      renderWithEditorContext(
         <BinaryFileHeader file={projectFile} storeReferencesKeys={() => {}} />
       )
       screen.getByText('Imported from', { exact: false })
@@ -78,7 +77,7 @@ describe('<BinaryFileHeader/>', function () {
     })
 
     it('Renders the correct text for a file with the project_output_file provider', function () {
-      render(
+      renderWithEditorContext(
         <BinaryFileHeader
           file={projectOutputFile}
           storeReferencesKeys={() => {}}
@@ -93,20 +92,6 @@ describe('<BinaryFileHeader/>', function () {
   })
 
   describe('The refresh button', async function () {
-    let reindexResponse
-
-    beforeEach(function () {
-      window.project_id = '123abc'
-      reindexResponse = {
-        projectId: '123abc',
-        keys: ['reference1', 'reference2', 'reference3', 'reference4'],
-      }
-    })
-
-    afterEach(function () {
-      delete window.project_id
-    })
-
     it('Changes text when the file is refreshing', async function () {
       fetchMock.post(
         'express:/project/:project_id/linked_file/:file_id/refresh',
@@ -115,7 +100,7 @@ describe('<BinaryFileHeader/>', function () {
         }
       )
 
-      render(
+      renderWithEditorContext(
         <BinaryFileHeader file={projectFile} storeReferencesKeys={() => {}} />
       )
 
@@ -135,12 +120,18 @@ describe('<BinaryFileHeader/>', function () {
         }
       )
 
+      const reindexResponse = {
+        projectId: '123abc',
+        keys: ['reference1', 'reference2', 'reference3', 'reference4'],
+      }
       fetchMock.post(
         'express:/project/:project_id/references/indexAll',
         reindexResponse
       )
 
-      render(
+      const storeReferencesKeys = sinon.stub()
+
+      renderWithEditorContext(
         <BinaryFileHeader
           file={thirdPartyReferenceFile}
           storeReferencesKeys={storeReferencesKeys}
@@ -160,7 +151,9 @@ describe('<BinaryFileHeader/>', function () {
 
   describe('The download button', function () {
     it('exists', function () {
-      render(<BinaryFileHeader file={urlFile} storeReferencesKeys={() => {}} />)
+      renderWithEditorContext(
+        <BinaryFileHeader file={urlFile} storeReferencesKeys={() => {}} />
+      )
 
       screen.getByText('Download', { exact: false })
     })

+ 3 - 2
services/web/test/frontend/features/binary-file/components/binary-file-image.test.js

@@ -1,6 +1,7 @@
 import React from 'react'
-import { render, screen } from '@testing-library/react'
+import { screen } from '@testing-library/react'
 
+import { renderWithEditorContext } from '../../../helpers/render-with-context'
 import BinaryFileImage from '../../../../../frontend/js/features/binary-file/components/binary-file-image.js'
 
 describe('<BinaryFileImage />', function () {
@@ -14,7 +15,7 @@ describe('<BinaryFileImage />', function () {
   }
 
   it('renders an image', function () {
-    render(
+    renderWithEditorContext(
       <BinaryFileImage
         fileName={file.name}
         fileId={file.id}

+ 5 - 7
services/web/test/frontend/features/binary-file/components/binary-file-text.test.js

@@ -1,7 +1,8 @@
 import React from 'react'
-import { render, screen } from '@testing-library/react'
+import { screen } from '@testing-library/react'
 import fetchMock from 'fetch-mock'
 
+import { renderWithEditorContext } from '../../../helpers/render-with-context'
 import BinaryFileText from '../../../../../frontend/js/features/binary-file/components/binary-file-text.js'
 
 describe('<BinaryFileText/>', function () {
@@ -18,11 +19,6 @@ describe('<BinaryFileText/>', function () {
 
   beforeEach(function () {
     fetchMock.reset()
-    window.project_id = '123abc'
-  })
-
-  afterEach(function () {
-    delete window.project_id
   })
 
   it('renders a text view', async function () {
@@ -35,7 +31,9 @@ describe('<BinaryFileText/>', function () {
       'Text file content'
     )
 
-    render(<BinaryFileText file={file} onError={() => {}} onLoad={() => {}} />)
+    renderWithEditorContext(
+      <BinaryFileText file={file} onError={() => {}} onLoad={() => {}} />
+    )
 
     await screen.findByText('Text file content', { exact: false })
   })

+ 17 - 9
services/web/test/frontend/features/binary-file/components/binary-file.test.js

@@ -1,12 +1,12 @@
 import React from 'react'
 import {
-  render,
   screen,
   waitForElementToBeRemoved,
   fireEvent,
 } from '@testing-library/react'
 import fetchMock from 'fetch-mock'
 
+import { renderWithEditorContext } from '../../../helpers/render-with-context'
 import BinaryFile from '../../../../../frontend/js/features/binary-file/components/binary-file.js'
 
 describe('<BinaryFile/>', function () {
@@ -35,16 +35,20 @@ describe('<BinaryFile/>', function () {
   })
 
   describe('for a text file', function () {
-    it('it shows a loading indicator while the file is loading', async function () {
-      render(<BinaryFile file={textFile} storeReferencesKeys={() => {}} />)
+    it('shows a loading indicator while the file is loading', async function () {
+      renderWithEditorContext(
+        <BinaryFile file={textFile} storeReferencesKeys={() => {}} />
+      )
 
       await waitForElementToBeRemoved(() =>
         screen.getByText('Loading', { exact: false })
       )
     })
 
-    it('it shows messaging if the text view could not be loaded', async function () {
-      render(<BinaryFile file={textFile} storeReferencesKeys={() => {}} />)
+    it('shows messaging if the text view could not be loaded', async function () {
+      renderWithEditorContext(
+        <BinaryFile file={textFile} storeReferencesKeys={() => {}} />
+      )
 
       await screen.findByText('Sorry, no preview is available', {
         exact: false,
@@ -53,14 +57,18 @@ describe('<BinaryFile/>', function () {
   })
 
   describe('for an image file', function () {
-    it('it shows a loading indicator while the file is loading', async function () {
-      render(<BinaryFile file={imageFile} storeReferencesKeys={() => {}} />)
+    it('shows a loading indicator while the file is loading', async function () {
+      renderWithEditorContext(
+        <BinaryFile file={imageFile} storeReferencesKeys={() => {}} />
+      )
 
       screen.getByText('Loading', { exact: false })
     })
 
-    it('it shows messaging if the image could not be loaded', function () {
-      render(<BinaryFile file={imageFile} storeReferencesKeys={() => {}} />)
+    it('shows messaging if the image could not be loaded', function () {
+      renderWithEditorContext(
+        <BinaryFile file={imageFile} storeReferencesKeys={() => {}} />
+      )
 
       // Fake the image request failing as the request is handled by the browser
       fireEvent.error(screen.getByRole('img'))