From c131873c82e53aa44bd316224f507aec3ccf54df Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Thu, 31 Aug 2023 17:38:53 +0000 Subject: [PATCH] add support for submodules and symlinks (#378) --- web/src/icons/CodeFileFill.svg | 7 +-- web/src/icons/Submodules.svg | 5 ++ web/src/icons/Symlink.svg | 4 ++ .../FileContent/FileContent.tsx | 21 ++++++- .../FolderContent/FolderContent.module.scss | 6 +- .../FolderContent/FolderContent.tsx | 56 ++++++++++++------- web/src/utils/FileUtils.ts | 30 ++++++++-- 7 files changed, 95 insertions(+), 34 deletions(-) create mode 100644 web/src/icons/Submodules.svg create mode 100644 web/src/icons/Symlink.svg diff --git a/web/src/icons/CodeFileFill.svg b/web/src/icons/CodeFileFill.svg index 7fb0d424b..666e07119 100644 --- a/web/src/icons/CodeFileFill.svg +++ b/web/src/icons/CodeFileFill.svg @@ -1,5 +1,4 @@ - - - - + + + diff --git a/web/src/icons/Submodules.svg b/web/src/icons/Submodules.svg new file mode 100644 index 000000000..1ab58b373 --- /dev/null +++ b/web/src/icons/Submodules.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/web/src/icons/Symlink.svg b/web/src/icons/Symlink.svg new file mode 100644 index 000000000..111a407a4 --- /dev/null +++ b/web/src/icons/Symlink.svg @@ -0,0 +1,4 @@ + + + + diff --git a/web/src/pages/Repository/RepositoryContent/FileContent/FileContent.tsx b/web/src/pages/Repository/RepositoryContent/FileContent/FileContent.tsx index cef781332..08a065234 100644 --- a/web/src/pages/Repository/RepositoryContent/FileContent/FileContent.tsx +++ b/web/src/pages/Repository/RepositoryContent/FileContent/FileContent.tsx @@ -35,7 +35,7 @@ import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButto import { PlainButton } from 'components/PlainButton/PlainButton' import { CommitsView } from 'components/CommitsView/CommitsView' import { useGetSpaceParam } from 'hooks/useGetSpaceParam' -import { FileCategory, useFileContentViewerDecision } from 'utils/FileUtils' +import { FileCategory, RepoContentExtended, useFileContentViewerDecision } from 'utils/FileUtils' import { useDownloadRawFile } from 'hooks/useDownloadRawFile' import { usePageIndex } from 'hooks/usePageIndex' import { Readme } from '../FolderContent/Readme' @@ -233,7 +233,12 @@ export function FileContent({ - + @@ -375,6 +380,18 @@ export function FileContent({ source={decodeGitContent(base64Data)} /> + + + + + + diff --git a/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.module.scss b/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.module.scss index de6d3865c..aa7b68da3 100644 --- a/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.module.scss +++ b/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.module.scss @@ -9,7 +9,7 @@ text-transform: none; color: var(--grey-400); font-weight: 500; - font-size: 13px; + font-size: 12px; } } @@ -24,7 +24,7 @@ margin-bottom: 0; .rowText { - font-size: 13px; + font-size: 12px; font-weight: 400; } } @@ -63,7 +63,7 @@ &, .text { - font-size: 13px; + font-size: 12px; font-weight: 400; cursor: pointer !important; } diff --git a/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx b/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx index d21e7a46d..2ebe40a33 100644 --- a/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx +++ b/web/src/pages/Repository/RepositoryContent/FolderContent/FolderContent.tsx @@ -9,10 +9,11 @@ import { TextProps, useIsMounted } from '@harnessio/uicore' -import { Icon } from '@harnessio/icons' import { Color } from '@harnessio/design-system' import cx from 'classnames' import type { CellProps, Column } from 'react-table' +import { Page } from 'iconoir-react' + import { Render } from 'react-jsx-match' import { chunk, sortBy, throttle } from 'lodash-es' import { useMutate } from 'restful-react' @@ -20,17 +21,30 @@ import { Link, useHistory } from 'react-router-dom' import { useAppContext } from 'AppContext' import type { OpenapiContentInfo, OpenapiDirContent, TypesCommit } from 'services/code' import { formatDate, isInViewport, LIST_FETCHING_LIMIT } from 'utils/Utils' -import { findReadmeInfo, CodeIcon, GitInfoProps, isFile } from 'utils/GitUtils' +import { findReadmeInfo, GitInfoProps, isFile, isSymlink, isSubmodule } from 'utils/GitUtils' import { LatestCommitForFolder } from 'components/LatestCommit/LatestCommit' import { CommitActions } from 'components/CommitActions/CommitActions' import { useEventListener } from 'hooks/useEventListener' import { Readme } from './Readme' import repositoryCSS from '../../Repository.module.scss' -import CodeFile from '../../../../icons/CodeFileFill.svg' +import CodeFolder from '../../../../icons/CodeFileFill.svg' +import Submodule from '../../../../icons/Submodules.svg' +import Symlink from '../../../../icons/Symlink.svg' import css from './FolderContent.module.scss' type FolderContentProps = Pick +const checkIcon = (row: OpenapiContentInfo): React.ReactElement => { + if (isFile(row)) { + return + } else if (isSymlink(row)) { + return + } else if (isSubmodule(row)) { + return + } else { + return + } +} export function FolderContent({ repoMetadata, resourceContent, gitRef }: FolderContentProps) { const history = useHistory() const { routes, standalone } = useAppContext() @@ -40,23 +54,25 @@ export function FolderContent({ repoMetadata, resourceContent, gitRef }: FolderC Header: 'Files', id: 'name', width: '30%', - Cell: ({ row }: CellProps) => ( - - - {isFile(row.original) ? : } - - - - ) + Cell: ({ row }: CellProps) => { + return ( + + + {checkIcon(row.original)} + + + + ) + } }, { Header: 'Date', diff --git a/web/src/utils/FileUtils.ts b/web/src/utils/FileUtils.ts index 397f45ff1..9d846b9bd 100644 --- a/web/src/utils/FileUtils.ts +++ b/web/src/utils/FileUtils.ts @@ -22,6 +22,13 @@ interface UseFileViewerDecisionResult { isText: boolean } +export interface RepoContentExtended extends RepoFileContent { + size?: number + target?: string + commit_sha?: string + url?: string +} + export function useFileContentViewerDecision({ repoMetadata, gitRef, @@ -32,6 +39,9 @@ export function useFileContentViewerDecision({ const metadata = useMemo(() => { const filename = resourceContent.name as string const extension = filename?.split('.').pop() || '' + const isSymlink = resourceContent?.type === 'symlink' + const isSubmodule = resourceContent?.type === 'submodule' + const isMarkdown = extension.toLowerCase() === 'md' const isPdf = extension.toLowerCase() === 'pdf' const isSVG = extension.toLowerCase() === 'svg' @@ -40,7 +50,9 @@ export function useFileContentViewerDecision({ const isVideo = VideoExtensions.includes(extension.toLowerCase()) const isText = !!( SpecialTextFiles.find(name => name.toLowerCase() === filename?.toLowerCase()) || - TextExtensions.includes(extension.toLowerCase()) + TextExtensions.includes(extension.toLowerCase()) || + isSymlink || + isSubmodule ) const category = isMarkdown ? FileCategory.MARKDOWN @@ -54,12 +66,17 @@ export function useFileContentViewerDecision({ ? FileCategory.AUDIO : isVideo ? FileCategory.VIDEO + : isSymlink + ? FileCategory.SYMLINK + : isSubmodule + ? FileCategory.SUBMODULE : isText ? FileCategory.TEXT : FileCategory.OTHER - const isViewable = isPdf || isSVG || isImage || isAudio || isVideo || isText - const resourceData = resourceContent?.content as RepoFileContent - const isFileTooLarge = resourceData?.size !== resourceData?.data_size + const isViewable = isPdf || isSVG || isImage || isAudio || isVideo || isText || isSubmodule || isSymlink + const resourceData = resourceContent?.content as RepoContentExtended + const isFileTooLarge = + resourceData?.size && resourceData?.data_size ? resourceData?.size !== resourceData?.data_size : false const rawURL = `/code/api/v1/repos/${repoMetadata?.path}/+/raw/${resourcePath}?routingId=${routingId}&git_ref=${gitRef}` return { category, @@ -73,7 +90,8 @@ export function useFileContentViewerDecision({ size: resourceData?.size || 0, // base64 data returned from content API. This snapshot can be truncated by backend - base64Data: resourceData?.data || '', + base64Data: resourceData?.data || resourceData?.target || resourceData?.url || '', + rawURL } }, [resourceContent.content]) // eslint-disable-line react-hooks/exhaustive-deps @@ -91,6 +109,8 @@ export enum FileCategory { AUDIO = 'AUDIO', VIDEO = 'VIDEO', TEXT = 'TEXT', + SYMLINK = 'SYMLINK', + SUBMODULE = 'SUBMODULE', OTHER = 'OTHER' }