From 496bb4d4e7220510f4bfbe63436a465cbc5e7c9e Mon Sep 17 00:00:00 2001 From: M Fahru Date: Wed, 27 Sep 2023 10:01:30 -0700 Subject: [PATCH] Merge pull request #14999 from overleaf/mf-file-view-header-typescript [web] Convert `file-view-header.js` to typescript GitOrigin-RevId: 1f05b086e3acb692f3745481c4022a920c4f7599 --- ...le-view-header.js => file-view-header.tsx} | 73 +++++++++---------- .../features/file-view/types/binary-file.ts | 44 +++++++++++ .../components/file-view-header.test.js | 2 +- services/web/types/window.ts | 1 + 4 files changed, 82 insertions(+), 38 deletions(-) rename services/web/frontend/js/features/file-view/components/{file-view-header.js => file-view-header.tsx} (83%) create mode 100644 services/web/frontend/js/features/file-view/types/binary-file.ts diff --git a/services/web/frontend/js/features/file-view/components/file-view-header.js b/services/web/frontend/js/features/file-view/components/file-view-header.tsx similarity index 83% rename from services/web/frontend/js/features/file-view/components/file-view-header.js rename to services/web/frontend/js/features/file-view/components/file-view-header.tsx index 5a7d8bb3d3..55667909d1 100644 --- a/services/web/frontend/js/features/file-view/components/file-view-header.js +++ b/services/web/frontend/js/features/file-view/components/file-view-header.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback } from 'react' +import { useState, useCallback, type ElementType } from 'react' import PropTypes from 'prop-types' import { Trans, useTranslation } from 'react-i18next' @@ -11,18 +11,27 @@ import { useProjectContext } from '../../../shared/context/project-context' import importOverleafModules from '../../../../macros/import-overleaf-module.macro' import useAbortController from '../../../shared/hooks/use-abort-controller' import { LinkedFileIcon } from './file-view-icons' +import { BinaryFile, hasProvider, LinkedFile } from '../types/binary-file' import { debugConsole } from '@/utils/debugging' -const tprLinkedFileInfo = importOverleafModules('tprLinkedFileInfo') + +const tprLinkedFileInfo = importOverleafModules('tprLinkedFileInfo') as { + import: { LinkedFileInfo: ElementType } + path: string +}[] + const tprLinkedFileRefreshError = importOverleafModules( 'tprLinkedFileRefreshError' -) +) as { + import: { LinkedFileRefreshError: ElementType } + path: string +}[] const MAX_URL_LENGTH = 60 const FRONT_OF_URL_LENGTH = 35 const FILLER = '...' const TAIL_OF_URL_LENGTH = MAX_URL_LENGTH - FRONT_OF_URL_LENGTH - FILLER.length -function shortenedUrl(url) { +function shortenedUrl(url: string) { if (!url) { return } @@ -34,7 +43,15 @@ function shortenedUrl(url) { return url } -export default function FileViewHeader({ file, storeReferencesKeys }) { +type FileViewHeaderProps = { + file: BinaryFile + storeReferencesKeys: (keys: string[]) => void +} + +export default function FileViewHeader({ + file, + storeReferencesKeys, +}: FileViewHeaderProps) { const { _id: projectId } = useProjectContext({ _id: PropTypes.string.isRequired, }) @@ -50,19 +67,19 @@ export default function FileViewHeader({ file, storeReferencesKeys }) { let fileInfo if (file.linkedFileData) { - if (file.linkedFileData.provider === 'url') { + if (hasProvider(file, 'url')) { fileInfo = (
) - } else if (file.linkedFileData.provider === 'project_file') { + } else if (hasProvider(file, 'project_file')) { fileInfo = (
) - } else if (file.linkedFileData.provider === 'project_output_file') { + } else if (hasProvider(file, 'project_output_file')) { fileInfo = (
@@ -85,8 +102,8 @@ export default function FileViewHeader({ file, storeReferencesKeys }) { }) .finally(() => { if ( - file.linkedFileData.provider === 'mendeley' || - file.linkedFileData.provider === 'zotero' || + hasProvider(file, 'mendeley') || + hasProvider(file, 'zotero') || file.name.match(/^.*\.bib$/) ) { reindexReferences() @@ -151,16 +168,11 @@ export default function FileViewHeader({ file, storeReferencesKeys }) { ) } -FileViewHeader.propTypes = { - file: PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - linkedFileData: PropTypes.object, - }).isRequired, - storeReferencesKeys: PropTypes.func.isRequired, +type UrlProviderProps = { + file: LinkedFile<'url'> } -function UrlProvider({ file }) { +function UrlProvider({ file }: UrlProviderProps) { return (

@@ -181,14 +193,11 @@ function UrlProvider({ file }) { ) } -UrlProvider.propTypes = { - file: PropTypes.shape({ - linkedFileData: PropTypes.object, - created: PropTypes.string, - }).isRequired, +type ProjectFilePathProviderProps = { + file: LinkedFile<'project_file'> } -function ProjectFilePathProvider({ file }) { +function ProjectFilePathProvider({ file }: ProjectFilePathProviderProps) { /* eslint-disable jsx-a11y/anchor-has-content, react/jsx-key */ return (

@@ -218,14 +227,11 @@ function ProjectFilePathProvider({ file }) { ) } -ProjectFilePathProvider.propTypes = { - file: PropTypes.shape({ - linkedFileData: PropTypes.object, - created: PropTypes.string, - }).isRequired, +type ProjectOutputFileProviderProps = { + file: LinkedFile<'project_output_file'> } -function ProjectOutputFileProvider({ file }) { +function ProjectOutputFileProvider({ file }: ProjectOutputFileProviderProps) { return (

@@ -252,10 +258,3 @@ function ProjectOutputFileProvider({ file }) {

) } - -ProjectOutputFileProvider.propTypes = { - file: PropTypes.shape({ - linkedFileData: PropTypes.object, - created: 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 new file mode 100644 index 0000000000..efed8be1d1 --- /dev/null +++ b/services/web/frontend/js/features/file-view/types/binary-file.ts @@ -0,0 +1,44 @@ +type LinkedFileData = { + url: { + provider: 'url' + url: string + } + zotero: { + provider: 'zotero' + importer_id: string + } + mendeley: { + provider: 'mendeley' + importer_id: string + } + project_file: { + provider: 'project_file' + v1_source_doc_id?: string + source_project_id: string + source_entity_path: string + } + project_output_file: { + provider: 'project_output_file' + v1_source_doc_id?: string + source_project_id: string + source_output_file_path: string + } +} + +export type BinaryFile = + { + _id: string + name: string + created: Date + id: string + type: string + selected: boolean + linkedFileData?: LinkedFileData[T] + } + +export type LinkedFile = Required> + +export const hasProvider = ( + file: BinaryFile, + provider: T +): file is LinkedFile => file.linkedFileData?.provider === provider diff --git a/services/web/test/frontend/features/file-view/components/file-view-header.test.js b/services/web/test/frontend/features/file-view/components/file-view-header.test.js index 6789462a3d..8fbc005028 100644 --- a/services/web/test/frontend/features/file-view/components/file-view-header.test.js +++ b/services/web/test/frontend/features/file-view/components/file-view-header.test.js @@ -8,7 +8,7 @@ import fetchMock from 'fetch-mock' import sinon from 'sinon' import { renderWithEditorContext } from '../../../helpers/render-with-context' -import FileViewHeader from '../../../../../frontend/js/features/file-view/components/file-view-header.js' +import FileViewHeader from '../../../../../frontend/js/features/file-view/components/file-view-header' describe('', function () { const urlFile = { diff --git a/services/web/types/window.ts b/services/web/types/window.ts index 68290269ae..ee97878621 100644 --- a/services/web/types/window.ts +++ b/services/web/types/window.ts @@ -39,5 +39,6 @@ declare global { enterprise?: boolean useRecaptchaNet?: boolean } + expectingLinkedFileRefreshedSocketFor?: string | null } }