From d932ec28e342499ce04dfdb31a9643ec8a2e224d Mon Sep 17 00:00:00 2001 From: Abdul Rahman <81605929+abdulrahmancodes@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:20:29 +0530 Subject: [PATCH] Show friendly message for non-previewable file previews (#16372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2025-12-06 at 12 50
42 AM Closes #15771 --- .../files/components/AttachmentRow.tsx | 29 +++------ .../files/components/DocumentViewer.tsx | 61 +++++++++++++++++++ 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/packages/twenty-front/src/modules/activities/files/components/AttachmentRow.tsx b/packages/twenty-front/src/modules/activities/files/components/AttachmentRow.tsx index efa575d5ce..c5d7061ac2 100644 --- a/packages/twenty-front/src/modules/activities/files/components/AttachmentRow.tsx +++ b/packages/twenty-front/src/modules/activities/files/components/AttachmentRow.tsx @@ -15,7 +15,6 @@ import styled from '@emotion/styled'; import { useState } from 'react'; import { isDefined } from 'twenty-shared/utils'; -import { PREVIEWABLE_EXTENSIONS } from '@/activities/files/const/previewable-extensions.const'; import { FileIcon } from '@/file/components/FileIcon'; import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag'; import { IconCalendar, OverflowingTextWithTooltip } from 'twenty-ui/display'; @@ -90,10 +89,6 @@ export const AttachmentRow = ({ const { name: originalFileName, extension: attachmentFileExtension } = getFileNameAndExtension(attachment.name); - const fileExtension = - attachmentFileExtension?.toLowerCase().replace('.', '') ?? ''; - const isPreviewable = PREVIEWABLE_EXTENSIONS.includes(fileExtension); - const [attachmentFileName, setAttachmentFileName] = useState(originalFileName); @@ -180,22 +175,14 @@ export const AttachmentRow = ({ /> ) : ( - {isPreviewable ? ( - - - - ) : ( - - - - )} + + + )} diff --git a/packages/twenty-front/src/modules/activities/files/components/DocumentViewer.tsx b/packages/twenty-front/src/modules/activities/files/components/DocumentViewer.tsx index e761accfb6..f97b52d678 100644 --- a/packages/twenty-front/src/modules/activities/files/components/DocumentViewer.tsx +++ b/packages/twenty-front/src/modules/activities/files/components/DocumentViewer.tsx @@ -1,5 +1,7 @@ import { PREVIEWABLE_EXTENSIONS } from '@/activities/files/const/previewable-extensions.const'; +import { downloadFile } from '@/activities/files/utils/downloadFile'; import { fetchCsvPreview } from '@/activities/files/utils/fetchCsvPreview'; +import { getFileType } from '@/activities/files/utils/getFileType'; import DocViewer, { DocViewerRenderers } from '@cyntler/react-doc-viewer'; import '@cyntler/react-doc-viewer/dist/index.css'; import { useTheme } from '@emotion/react'; @@ -7,6 +9,8 @@ import styled from '@emotion/styled'; import { Trans } from '@lingui/react/macro'; import { useEffect, useState } from 'react'; import { isDefined } from 'twenty-shared/utils'; +import { IconDownload } from 'twenty-ui/display'; +import { Button } from 'twenty-ui/input'; import { getFileNameAndExtension } from '~/utils/file/getFileNameAndExtension'; const StyledDocumentViewerContainer = styled.div` @@ -37,6 +41,29 @@ const StyledDocumentViewerContainer = styled.div` } `; +const StyledUnavailablePreviewContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + gap: ${({ theme }) => theme.spacing(4)}; + padding: ${({ theme }) => theme.spacing(8)}; + text-align: center; +`; + +const StyledMessage = styled.div` + color: ${({ theme }) => theme.font.color.secondary}; + font-size: ${({ theme }) => theme.font.size.lg}; + max-width: 400px; +`; + +const StyledTitle = styled.div` + color: ${({ theme }) => theme.font.color.primary}; + font-size: ${({ theme }) => theme.font.size.xl}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; +`; + type DocumentViewerProps = { documentName: string; documentUrl: string; @@ -77,6 +104,9 @@ export const DocumentViewer = ({ const { extension } = getFileNameAndExtension(documentName); const fileExtension = extension?.toLowerCase().replace('.', '') ?? ''; + const fileCategory = getFileType(documentName); + const isPreviewable = PREVIEWABLE_EXTENSIONS.includes(fileExtension); + const mimeType = PREVIEWABLE_EXTENSIONS.includes(fileExtension) ? MIME_TYPE_MAPPING[fileExtension] : undefined; @@ -89,6 +119,37 @@ export const DocumentViewer = ({ } }, [documentUrl, fileExtension]); + if (!isPreviewable) { + return ( + + + + Preview Not Available + + + {fileCategory === 'ARCHIVE' ? ( + + Archive files cannot be previewed. Please download the file to + access its contents. + + ) : ( + + This file type cannot be previewed. Please download the file to + view it. + + )} + +