diff --git a/services/web/frontend/js/features/file-view/components/file-view-icons.jsx b/services/web/frontend/js/features/file-view/components/file-view-icons.jsx
deleted file mode 100644
index 8016d098cb..0000000000
--- a/services/web/frontend/js/features/file-view/components/file-view-icons.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import MaterialIcon from '@/shared/components/material-icon'
-
-export const LinkedFileIcon = props => {
- return (
-
- )
-}
diff --git a/services/web/frontend/js/features/file-view/components/file-view-icons.tsx b/services/web/frontend/js/features/file-view/components/file-view-icons.tsx
new file mode 100644
index 0000000000..168f7be5e8
--- /dev/null
+++ b/services/web/frontend/js/features/file-view/components/file-view-icons.tsx
@@ -0,0 +1,14 @@
+import MaterialIcon, { IconProps } from '@/shared/components/material-icon'
+
+export const LinkedFileIcon = (
+ props: Omit
+) => {
+ return (
+
+ )
+}
diff --git a/services/web/frontend/js/features/file-view/components/file-view.jsx b/services/web/frontend/js/features/file-view/components/file-view.tsx
similarity index 83%
rename from services/web/frontend/js/features/file-view/components/file-view.jsx
rename to services/web/frontend/js/features/file-view/components/file-view.tsx
index 711d125fe9..b84ee383eb 100644
--- a/services/web/frontend/js/features/file-view/components/file-view.jsx
+++ b/services/web/frontend/js/features/file-view/components/file-view.tsx
@@ -1,5 +1,4 @@
import { useState, useCallback } from 'react'
-import PropTypes from 'prop-types'
import { useTranslation } from 'react-i18next'
import FileViewHeader from './file-view-header'
@@ -8,10 +7,11 @@ import FileViewPdf from './file-view-pdf'
import FileViewText from './file-view-text'
import LoadingSpinner from '@/shared/components/loading-spinner'
import getMeta from '@/utils/meta'
+import { BinaryFile } from '../types/binary-file'
const imageExtensions = ['png', 'jpg', 'jpeg', 'gif']
-export default function FileView({ file }) {
+export default function FileView({ file }: { file: BinaryFile }) {
const [contentLoading, setContentLoading] = useState(true)
const [hasError, setHasError] = useState(false)
@@ -19,13 +19,13 @@ export default function FileView({ file }) {
const { textExtensions, editableFilenames } = getMeta('ol-ExposedSettings')
- const extension = file.name.split('.').pop().toLowerCase()
+ const extension = file.name.split('.')?.pop()?.toLowerCase()
const isEditableTextFile =
- textExtensions.includes(extension) ||
+ (extension && textExtensions.includes(extension)) ||
editableFilenames.includes(file.name.toLowerCase())
- const isImageFile = imageExtensions.includes(extension)
+ const isImageFile = !!extension && imageExtensions.includes(extension)
const isPdfFile = extension === 'pdf'
const isUnpreviewableFile = !isEditableTextFile && !isImageFile && !isPdfFile
@@ -80,11 +80,3 @@ function FileViewLoadingIndicator() {
)
}
-
-FileView.propTypes = {
- file: PropTypes.shape({
- id: PropTypes.string,
- name: PropTypes.string,
- hash: PropTypes.string,
- }).isRequired,
-}
diff --git a/services/web/frontend/js/features/file-view/types/binary-file.ts b/services/web/frontend/js/features/file-view/types/binary-file.ts
index a52bc0edb9..4a4104615c 100644
--- a/services/web/frontend/js/features/file-view/types/binary-file.ts
+++ b/services/web/frontend/js/features/file-view/types/binary-file.ts
@@ -21,7 +21,7 @@ export type BinaryFile =
{
_id: string
name: string
- created: Date
+ created: Date | string
id: string
type: string
selected: boolean
diff --git a/services/web/frontend/js/features/ide-react/util/file-view.ts b/services/web/frontend/js/features/ide-react/util/file-view.ts
index e32f3bb4ee..7247450c71 100644
--- a/services/web/frontend/js/features/ide-react/util/file-view.ts
+++ b/services/web/frontend/js/features/ide-react/util/file-view.ts
@@ -22,10 +22,10 @@ export function convertFileRefToBinaryFile(fileRef: FileRef): BinaryFile {
// is the only one making runtime complaints and it seems that other uses of
// `FileViewHeader` pass in a string for `created`, so that's what this function
// does too.
-export function fileViewFile(fileRef: FileRef) {
+export function fileViewFile(fileRef: FileRef): BinaryFile {
const converted = convertFileRefToBinaryFile(fileRef)
return {
...converted,
- created: converted.created.toISOString(),
+ created: (converted.created as Date).toISOString(),
}
}
diff --git a/services/web/frontend/js/shared/components/material-icon.tsx b/services/web/frontend/js/shared/components/material-icon.tsx
index be351d16bb..a5bd97e83c 100644
--- a/services/web/frontend/js/shared/components/material-icon.tsx
+++ b/services/web/frontend/js/shared/components/material-icon.tsx
@@ -20,7 +20,7 @@ type UnfilledIconProps = BaseIconProps & {
unfilled: true
}
-type IconProps = FilledIconProps | UnfilledIconProps
+export type IconProps = FilledIconProps | UnfilledIconProps
function MaterialIcon({
type,
diff --git a/services/web/test/frontend/features/file-view/components/file-view-header.test.jsx b/services/web/test/frontend/features/file-view/components/file-view-header.test.tsx
similarity index 72%
rename from services/web/test/frontend/features/file-view/components/file-view-header.test.jsx
rename to services/web/test/frontend/features/file-view/components/file-view-header.test.tsx
index 11a61d9905..730727e33e 100644
--- a/services/web/test/frontend/features/file-view/components/file-view-header.test.jsx
+++ b/services/web/test/frontend/features/file-view/components/file-view-header.test.tsx
@@ -5,39 +5,9 @@ import { renderWithEditorContext } from '../../../helpers/render-with-context'
import FileViewHeader from '../../../../../frontend/js/features/file-view/components/file-view-header'
import { USER_ID } from '../../../helpers/editor-providers'
import { fileViewFile } from '@/features/ide-react/util/file-view'
+import { projectOutputFile, textFile, urlFile } from '../util/files'
describe('', function () {
- const urlFile = {
- name: 'example.tex',
- linkedFileData: {
- url: 'https://overleaf.com',
- provider: 'url',
- },
- created: new Date(2021, 1, 17, 3, 24).toISOString(),
- }
-
- const projectFile = {
- name: 'example.tex',
- linkedFileData: {
- v1_source_doc_id: 'v1-source-id',
- source_project_id: 'source-project-id',
- source_entity_path: '/source-entity-path.ext',
- provider: 'project_file',
- importer_id: USER_ID,
- },
- created: new Date(2021, 1, 17, 3, 24).toISOString(),
- }
-
- const projectOutputFile = {
- name: 'example.pdf',
- linkedFileData: {
- v1_source_doc_id: 'v1-source-id',
- source_output_file_path: '/source-entity-path.ext',
- provider: 'project_output_file',
- },
- created: new Date(2021, 1, 17, 3, 24).toISOString(),
- }
-
beforeEach(function () {
fetchMock.removeRoutes().clearHistory()
})
@@ -52,7 +22,7 @@ describe('', function () {
})
it('Renders the correct text for a file with the project_file provider', function () {
- renderWithEditorContext()
+ renderWithEditorContext()
screen.getByText('Imported from', { exact: false })
screen.getByText('Another project', { exact: false })
screen.getByText('/source-entity-path.ext, at 3:24 am Wed, 17th Feb 21', {
@@ -61,12 +31,7 @@ describe('', function () {
})
it('Renders the correct text for a file with the project_output_file provider', function () {
- renderWithEditorContext(
- {}}
- />
- )
+ renderWithEditorContext()
screen.getByText('Imported from the output of', { exact: false })
screen.getByText('Another project', { exact: false })
screen.getByText('/source-entity-path.ext, at 3:24 am Wed, 17th Feb 21', {
@@ -85,6 +50,8 @@ describe('', function () {
it('should use importedAt as timestamp when present in the linked file data', function () {
const fileFromServer = {
+ _id: 'some-id',
+ hash: 'some-hash',
name: 'example.tex',
linkedFileData: {
v1_source_doc_id: 'v1-source-id',
diff --git a/services/web/test/frontend/features/file-view/components/file-view-image.test.jsx b/services/web/test/frontend/features/file-view/components/file-view-image.test.tsx
similarity index 57%
rename from services/web/test/frontend/features/file-view/components/file-view-image.test.jsx
rename to services/web/test/frontend/features/file-view/components/file-view-image.test.tsx
index 7ff204cc2e..7a2486a0b2 100644
--- a/services/web/test/frontend/features/file-view/components/file-view-image.test.jsx
+++ b/services/web/test/frontend/features/file-view/components/file-view-image.test.tsx
@@ -2,21 +2,12 @@ import { screen } from '@testing-library/react'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
import FileViewImage from '../../../../../frontend/js/features/file-view/components/file-view-image'
+import { imageFile } from '../util/files'
describe('', function () {
- const file = {
- id: '60097ca20454610027c442a8',
- name: 'file.jpg',
- hash: 'hash',
- linkedFileData: {
- source_entity_path: '/source-entity-path',
- provider: 'project_file',
- },
- }
-
it('renders an image', function () {
renderWithEditorContext(
- {}} onLoad={() => {}} />
+ {}} onLoad={() => {}} />
)
screen.getByRole('img')
})
diff --git a/services/web/test/frontend/features/file-view/components/file-view-refresh-button.test.jsx b/services/web/test/frontend/features/file-view/components/file-view-refresh-button.test.tsx
similarity index 66%
rename from services/web/test/frontend/features/file-view/components/file-view-refresh-button.test.jsx
rename to services/web/test/frontend/features/file-view/components/file-view-refresh-button.test.tsx
index da29252be0..c421f94771 100644
--- a/services/web/test/frontend/features/file-view/components/file-view-refresh-button.test.jsx
+++ b/services/web/test/frontend/features/file-view/components/file-view-refresh-button.test.tsx
@@ -7,21 +7,9 @@ import fetchMock from 'fetch-mock'
import sinon from 'sinon'
import FileViewRefreshButton from '@/features/file-view/components/file-view-refresh-button'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
-import { USER_ID } from '../../../helpers/editor-providers'
+import { textFile } from '../util/files'
describe('', function () {
- const projectFile = {
- name: 'example.tex',
- linkedFileData: {
- v1_source_doc_id: 'v1-source-id',
- source_project_id: 'source-project-id',
- source_entity_path: '/source-entity-path.ext',
- provider: 'project_file',
- importer_id: USER_ID,
- },
- created: new Date(2021, 1, 17, 3, 24).toISOString(),
- }
-
beforeEach(function () {
fetchMock.removeRoutes().clearHistory()
})
@@ -36,10 +24,7 @@ describe('', function () {
)
renderWithEditorContext(
-
+
)
fireEvent.click(screen.getByRole('button', { name: 'Refresh' }))
diff --git a/services/web/test/frontend/features/file-view/components/file-view-refresh-error.test.tsx b/services/web/test/frontend/features/file-view/components/file-view-refresh-error.test.tsx
index c4aa796fcc..8d66975655 100644
--- a/services/web/test/frontend/features/file-view/components/file-view-refresh-error.test.tsx
+++ b/services/web/test/frontend/features/file-view/components/file-view-refresh-error.test.tsx
@@ -1,29 +1,11 @@
import { render, screen } from '@testing-library/react'
import FileViewRefreshError from '@/features/file-view/components/file-view-refresh-error'
-import type { BinaryFile } from '@/features/file-view/types/binary-file'
+import { imageFile } from '../util/files'
describe('', function () {
it('shows correct error message', function () {
- const anotherProjectFile: BinaryFile<'project_file'> = {
- id: '123abc',
- _id: '123abc',
- linkedFileData: {
- provider: 'project_file',
- source_project_id: 'some-id',
- source_entity_path: '/path/',
- },
- created: new Date(2023, 1, 17, 3, 24),
- name: 'frog.jpg',
- type: 'file',
- selected: true,
- hash: '42',
- }
-
render(
-
+
)
screen.getByText('Access Denied: An error message')
diff --git a/services/web/test/frontend/features/file-view/components/file-view-text.test.jsx b/services/web/test/frontend/features/file-view/components/file-view-text.test.tsx
similarity index 67%
rename from services/web/test/frontend/features/file-view/components/file-view-text.test.jsx
rename to services/web/test/frontend/features/file-view/components/file-view-text.test.tsx
index 1ca50fbb8c..6c59bf3fe8 100644
--- a/services/web/test/frontend/features/file-view/components/file-view-text.test.jsx
+++ b/services/web/test/frontend/features/file-view/components/file-view-text.test.tsx
@@ -3,21 +3,9 @@ import fetchMock from 'fetch-mock'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
import FileViewText from '../../../../../frontend/js/features/file-view/components/file-view-text'
+import { textFile } from '../util/files'
describe('', function () {
- const file = {
- id: '123',
- hash: '1234',
- name: 'example.tex',
- linkedFileData: {
- v1_source_doc_id: 'v1-source-id',
- source_project_id: 'source-project-id',
- source_entity_path: '/source-entity-path.ext',
- provider: 'project_file',
- },
- created: new Date(2021, 1, 17, 3, 24).toISOString(),
- }
-
beforeEach(function () {
fetchMock.removeRoutes().clearHistory()
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
@@ -34,7 +22,7 @@ describe('', function () {
)
renderWithEditorContext(
- {}} onLoad={() => {}} />
+ {}} onLoad={() => {}} />
)
await screen.findByText('Text file content', { exact: false })
diff --git a/services/web/test/frontend/features/file-view/components/file-view.test.jsx b/services/web/test/frontend/features/file-view/components/file-view.test.tsx
similarity index 78%
rename from services/web/test/frontend/features/file-view/components/file-view.test.jsx
rename to services/web/test/frontend/features/file-view/components/file-view.test.tsx
index 7159f1ceaf..a3b6de7661 100644
--- a/services/web/test/frontend/features/file-view/components/file-view.test.jsx
+++ b/services/web/test/frontend/features/file-view/components/file-view.test.tsx
@@ -7,30 +7,9 @@ import fetchMock from 'fetch-mock'
import { renderWithEditorContext } from '../../../helpers/render-with-context'
import FileView from '../../../../../frontend/js/features/file-view/components/file-view'
+import { imageFile, textFile } from '../util/files'
describe('', function () {
- const textFile = {
- id: 'text-file',
- name: 'example.tex',
- linkedFileData: {
- v1_source_doc_id: 'v1-source-id',
- source_project_id: 'source-project-id',
- source_entity_path: '/source-entity-path.ext',
- provider: 'project_file',
- },
- hash: '012345678901234567890123',
- created: new Date(2021, 1, 17, 3, 24).toISOString(),
- }
-
- const imageFile = {
- id: '60097ca20454610027c442a8',
- name: 'file.jpg',
- linkedFileData: {
- source_entity_path: '/source-entity-path',
- provider: 'project_file',
- },
- }
-
beforeEach(function () {
fetchMock.removeRoutes().clearHistory()
window.metaAttributesCache.set('ol-preventCompileOnLoad', true)
diff --git a/services/web/test/frontend/features/file-view/util/files.ts b/services/web/test/frontend/features/file-view/util/files.ts
new file mode 100644
index 0000000000..ff9355d721
--- /dev/null
+++ b/services/web/test/frontend/features/file-view/util/files.ts
@@ -0,0 +1,62 @@
+import { BinaryFile } from '@/features/file-view/types/binary-file'
+
+export const textFile: BinaryFile<'project_file'> = {
+ _id: 'text-file',
+ id: 'text-file',
+ name: 'example.tex',
+ linkedFileData: {
+ v1_source_doc_id: 'v1-source-id',
+ source_project_id: 'source-project-id',
+ source_entity_path: '/source-entity-path.ext',
+ provider: 'project_file',
+ },
+ hash: '012345678901234567890123',
+ created: new Date(2021, 1, 17, 3, 24).toISOString(),
+ type: 'file',
+ selected: true,
+}
+
+export const imageFile: BinaryFile<'project_file'> = {
+ _id: '60097ca20454610027c442a8',
+ id: '60097ca20454610027c442a8',
+ name: 'file.jpg',
+ linkedFileData: {
+ source_project_id: 'source-project-id',
+ source_entity_path: '/source-entity-path',
+ provider: 'project_file',
+ },
+ hash: '012345678901234567890123',
+ created: new Date(2021, 1, 17, 3, 24).toISOString(),
+ type: 'file',
+ selected: true,
+}
+
+export const urlFile: BinaryFile<'url'> = {
+ _id: 'url-file',
+ id: 'url-file',
+ name: 'example.tex',
+ linkedFileData: {
+ url: 'https://overleaf.com',
+ provider: 'url',
+ },
+ created: new Date(2021, 1, 17, 3, 24).toISOString(),
+ hash: 'some-hash',
+ type: 'file',
+ selected: true,
+}
+
+export const projectOutputFile: BinaryFile<'project_output_file'> = {
+ _id: 'project-output-file',
+ id: 'project-output-file',
+ name: 'example.pdf',
+ linkedFileData: {
+ v1_source_doc_id: 'v1-source-id',
+ source_output_file_path: '/source-entity-path.ext',
+ provider: 'project_output_file',
+ source_project_id: 'source-project-id',
+ },
+ created: new Date(2021, 1, 17, 3, 24).toISOString(),
+ hash: 'some-hash',
+ type: 'file',
+ selected: true,
+}