mirror of
https://github.com/harness/drone.git
synced 2025-05-31 11:43:15 +00:00
add support for submodules and symlinks (#378)
This commit is contained in:
parent
ac8f1932ba
commit
c131873c82
@ -1,5 +1,4 @@
|
|||||||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M15.3333 6.30333H13.3333V4.66699H7.99996L6.66663 2.66699H2.66663V13.3337M15.3333 6.30333L13.3333 13.3337H2.66663M15.3333 6.30333H4.66663L2.66663 13.3337" stroke="#383946" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M1.16406 6.41683V2.6835C1.16406 2.59067 1.20094 2.50165 1.26658 2.43601C1.33221 2.37037 1.42124 2.3335 1.51406 2.3335H5.1179C5.20132 2.33349 5.282 2.36328 5.3454 2.4175L7.19106 3.9995C7.25446 4.05371 7.33514 4.0835 7.41856 4.0835H12.4807C12.5267 4.0835 12.5722 4.09255 12.6147 4.11014C12.6571 4.12773 12.6957 4.15351 12.7282 4.18601C12.7607 4.21851 12.7865 4.25709 12.8041 4.29956C12.8217 4.34202 12.8307 4.38753 12.8307 4.4335V6.41683M1.16406 6.41683V11.3168C1.16406 11.4097 1.20094 11.4987 1.26658 11.5643C1.33221 11.63 1.42124 11.6668 1.51406 11.6668H12.4807C12.5736 11.6668 12.6626 11.63 12.7282 11.5643C12.7939 11.4987 12.8307 11.4097 12.8307 11.3168V6.41683M1.16406 6.41683H6.9974H12.8307" stroke="#4F5162" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M15 6.5H4.5L3 13H13L15 6.5Z" fill="#383946"/>
|
<rect x="1" y="6" width="12" height="6" fill="#4F5162"/>
|
||||||
<path opacity="0.3" d="M8.66663 2.66634H13.3333" stroke="#383946" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 929 B |
5
web/src/icons/Submodules.svg
Normal file
5
web/src/icons/Submodules.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1.16406 6.41683V2.6835C1.16406 2.59067 1.20094 2.50165 1.26658 2.43601C1.33221 2.37037 1.42124 2.3335 1.51406 2.3335H5.1179C5.20132 2.33349 5.282 2.36328 5.3454 2.4175L7.19106 3.9995C7.25446 4.05371 7.33514 4.0835 7.41856 4.0835H12.4807C12.5267 4.0835 12.5722 4.09255 12.6147 4.11014C12.6571 4.12773 12.6957 4.15351 12.7282 4.18601C12.7607 4.21851 12.7865 4.25709 12.8041 4.29956C12.8217 4.34202 12.8307 4.38753 12.8307 4.4335V6.41683M1.16406 6.41683V11.3168C1.16406 11.4097 1.20094 11.4987 1.26658 11.5643C1.33221 11.63 1.42124 11.6668 1.51406 11.6668H12.4807C12.5736 11.6668 12.6626 11.63 12.7282 11.5643C12.7939 11.4987 12.8307 11.4097 12.8307 11.3168V6.41683M1.16406 6.41683H6.9974H12.8307" stroke="#4F5162" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<rect x="1" y="6" width="12" height="6" fill="#4F5162"/>
|
||||||
|
<path d="M7 7.6665L8.33333 8.99984M8.33333 8.99984H5M8.33333 8.99984L7 10.3332" stroke="white" stroke-width="0.88" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
4
web/src/icons/Symlink.svg
Normal file
4
web/src/icons/Symlink.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7 7.6665L8.33333 8.99984M8.33333 8.99984H5M8.33333 8.99984L7 10.3332M2.33594 12.4832V1.5165C2.33594 1.42368 2.37281 1.33465 2.43845 1.26902C2.50409 1.20338 2.59311 1.1665 2.68594 1.1665H9.48294C9.57573 1.16659 9.6647 1.20351 9.73027 1.26917L11.5666 3.1055C11.5993 3.13811 11.6251 3.17685 11.6428 3.2195C11.6604 3.26215 11.6694 3.30786 11.6693 3.354V12.4832C11.6693 12.5291 11.6602 12.5746 11.6426 12.6171C11.625 12.6596 11.5993 12.6982 11.5668 12.7307C11.5343 12.7632 11.4957 12.7889 11.4532 12.8065C11.4107 12.8241 11.3652 12.8332 11.3193 12.8332H2.68594C2.63997 12.8332 2.59446 12.8241 2.552 12.8065C2.50953 12.7889 2.47095 12.7632 2.43845 12.7307C2.40595 12.6982 2.38017 12.6596 2.36258 12.6171C2.34499 12.5746 2.33594 12.5291 2.33594 12.4832Z" stroke="#4F5162" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M9.33594 1.1665V3.14984C9.33594 3.24266 9.37281 3.33169 9.43845 3.39732C9.50409 3.46296 9.59311 3.49984 9.68594 3.49984H11.6693" stroke="#4F5162" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -35,7 +35,7 @@ import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButto
|
|||||||
import { PlainButton } from 'components/PlainButton/PlainButton'
|
import { PlainButton } from 'components/PlainButton/PlainButton'
|
||||||
import { CommitsView } from 'components/CommitsView/CommitsView'
|
import { CommitsView } from 'components/CommitsView/CommitsView'
|
||||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||||
import { FileCategory, useFileContentViewerDecision } from 'utils/FileUtils'
|
import { FileCategory, RepoContentExtended, useFileContentViewerDecision } from 'utils/FileUtils'
|
||||||
import { useDownloadRawFile } from 'hooks/useDownloadRawFile'
|
import { useDownloadRawFile } from 'hooks/useDownloadRawFile'
|
||||||
import { usePageIndex } from 'hooks/usePageIndex'
|
import { usePageIndex } from 'hooks/usePageIndex'
|
||||||
import { Readme } from '../FolderContent/Readme'
|
import { Readme } from '../FolderContent/Readme'
|
||||||
@ -233,7 +233,12 @@ export function FileContent({
|
|||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
|
|
||||||
<Render when={(resourceContent?.content as RepoFileContent)?.data}>
|
<Render
|
||||||
|
when={
|
||||||
|
(resourceContent?.content as RepoFileContent)?.data ||
|
||||||
|
(resourceContent?.content as RepoContentExtended)?.target ||
|
||||||
|
(resourceContent?.content as RepoContentExtended)?.url
|
||||||
|
}>
|
||||||
<Container className={css.content}>
|
<Container className={css.content}>
|
||||||
<Match expr={isViewable}>
|
<Match expr={isViewable}>
|
||||||
<Falsy>
|
<Falsy>
|
||||||
@ -375,6 +380,18 @@ export function FileContent({
|
|||||||
source={decodeGitContent(base64Data)}
|
source={decodeGitContent(base64Data)}
|
||||||
/>
|
/>
|
||||||
</Case>
|
</Case>
|
||||||
|
<Case val={FileCategory.SUBMODULE}>
|
||||||
|
<SourceCodeViewer
|
||||||
|
language={filenameToLanguage(filename)}
|
||||||
|
source={decodeGitContent(base64Data)}
|
||||||
|
/>
|
||||||
|
</Case>
|
||||||
|
<Case val={FileCategory.SYMLINK}>
|
||||||
|
<SourceCodeViewer
|
||||||
|
language={filenameToLanguage(filename)}
|
||||||
|
source={decodeGitContent(base64Data)}
|
||||||
|
/>
|
||||||
|
</Case>
|
||||||
</Match>
|
</Match>
|
||||||
</Center>
|
</Center>
|
||||||
</Falsy>
|
</Falsy>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
text-transform: none;
|
text-transform: none;
|
||||||
color: var(--grey-400);
|
color: var(--grey-400);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
.rowText {
|
.rowText {
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@
|
|||||||
|
|
||||||
&,
|
&,
|
||||||
.text {
|
.text {
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
cursor: pointer !important;
|
cursor: pointer !important;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ import {
|
|||||||
TextProps,
|
TextProps,
|
||||||
useIsMounted
|
useIsMounted
|
||||||
} from '@harnessio/uicore'
|
} from '@harnessio/uicore'
|
||||||
import { Icon } from '@harnessio/icons'
|
|
||||||
import { Color } from '@harnessio/design-system'
|
import { Color } from '@harnessio/design-system'
|
||||||
import cx from 'classnames'
|
import cx from 'classnames'
|
||||||
import type { CellProps, Column } from 'react-table'
|
import type { CellProps, Column } from 'react-table'
|
||||||
|
import { Page } from 'iconoir-react'
|
||||||
|
|
||||||
import { Render } from 'react-jsx-match'
|
import { Render } from 'react-jsx-match'
|
||||||
import { chunk, sortBy, throttle } from 'lodash-es'
|
import { chunk, sortBy, throttle } from 'lodash-es'
|
||||||
import { useMutate } from 'restful-react'
|
import { useMutate } from 'restful-react'
|
||||||
@ -20,17 +21,30 @@ import { Link, useHistory } from 'react-router-dom'
|
|||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import type { OpenapiContentInfo, OpenapiDirContent, TypesCommit } from 'services/code'
|
import type { OpenapiContentInfo, OpenapiDirContent, TypesCommit } from 'services/code'
|
||||||
import { formatDate, isInViewport, LIST_FETCHING_LIMIT } from 'utils/Utils'
|
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 { LatestCommitForFolder } from 'components/LatestCommit/LatestCommit'
|
||||||
import { CommitActions } from 'components/CommitActions/CommitActions'
|
import { CommitActions } from 'components/CommitActions/CommitActions'
|
||||||
import { useEventListener } from 'hooks/useEventListener'
|
import { useEventListener } from 'hooks/useEventListener'
|
||||||
import { Readme } from './Readme'
|
import { Readme } from './Readme'
|
||||||
import repositoryCSS from '../../Repository.module.scss'
|
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'
|
import css from './FolderContent.module.scss'
|
||||||
|
|
||||||
type FolderContentProps = Pick<GitInfoProps, 'repoMetadata' | 'resourceContent' | 'gitRef'>
|
type FolderContentProps = Pick<GitInfoProps, 'repoMetadata' | 'resourceContent' | 'gitRef'>
|
||||||
|
|
||||||
|
const checkIcon = (row: OpenapiContentInfo): React.ReactElement => {
|
||||||
|
if (isFile(row)) {
|
||||||
|
return <Page width={14} height={14} />
|
||||||
|
} else if (isSymlink(row)) {
|
||||||
|
return <img width={14} height={14} src={Symlink} />
|
||||||
|
} else if (isSubmodule(row)) {
|
||||||
|
return <img width={14} height={14} src={Submodule} />
|
||||||
|
} else {
|
||||||
|
return <img width={14} height={14} src={CodeFolder} />
|
||||||
|
}
|
||||||
|
}
|
||||||
export function FolderContent({ repoMetadata, resourceContent, gitRef }: FolderContentProps) {
|
export function FolderContent({ repoMetadata, resourceContent, gitRef }: FolderContentProps) {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const { routes, standalone } = useAppContext()
|
const { routes, standalone } = useAppContext()
|
||||||
@ -40,10 +54,11 @@ export function FolderContent({ repoMetadata, resourceContent, gitRef }: FolderC
|
|||||||
Header: 'Files',
|
Header: 'Files',
|
||||||
id: 'name',
|
id: 'name',
|
||||||
width: '30%',
|
width: '30%',
|
||||||
Cell: ({ row }: CellProps<OpenapiContentInfo>) => (
|
Cell: ({ row }: CellProps<OpenapiContentInfo>) => {
|
||||||
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Layout.Horizontal spacing="small">
|
<Layout.Horizontal spacing="small">
|
||||||
{isFile(row.original) ? <Icon name={CodeIcon.File} /> : <img width={16} height={16} src={CodeFile} />}
|
{checkIcon(row.original)}
|
||||||
<ListingItemLink
|
<ListingItemLink
|
||||||
url={routes.toCODERepository({
|
url={routes.toCODERepository({
|
||||||
repoPath: repoMetadata.path as string,
|
repoPath: repoMetadata.path as string,
|
||||||
@ -57,6 +72,7 @@ export function FolderContent({ repoMetadata, resourceContent, gitRef }: FolderC
|
|||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Date',
|
Header: 'Date',
|
||||||
|
@ -22,6 +22,13 @@ interface UseFileViewerDecisionResult {
|
|||||||
isText: boolean
|
isText: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RepoContentExtended extends RepoFileContent {
|
||||||
|
size?: number
|
||||||
|
target?: string
|
||||||
|
commit_sha?: string
|
||||||
|
url?: string
|
||||||
|
}
|
||||||
|
|
||||||
export function useFileContentViewerDecision({
|
export function useFileContentViewerDecision({
|
||||||
repoMetadata,
|
repoMetadata,
|
||||||
gitRef,
|
gitRef,
|
||||||
@ -32,6 +39,9 @@ export function useFileContentViewerDecision({
|
|||||||
const metadata = useMemo(() => {
|
const metadata = useMemo(() => {
|
||||||
const filename = resourceContent.name as string
|
const filename = resourceContent.name as string
|
||||||
const extension = filename?.split('.').pop() || ''
|
const extension = filename?.split('.').pop() || ''
|
||||||
|
const isSymlink = resourceContent?.type === 'symlink'
|
||||||
|
const isSubmodule = resourceContent?.type === 'submodule'
|
||||||
|
|
||||||
const isMarkdown = extension.toLowerCase() === 'md'
|
const isMarkdown = extension.toLowerCase() === 'md'
|
||||||
const isPdf = extension.toLowerCase() === 'pdf'
|
const isPdf = extension.toLowerCase() === 'pdf'
|
||||||
const isSVG = extension.toLowerCase() === 'svg'
|
const isSVG = extension.toLowerCase() === 'svg'
|
||||||
@ -40,7 +50,9 @@ export function useFileContentViewerDecision({
|
|||||||
const isVideo = VideoExtensions.includes(extension.toLowerCase())
|
const isVideo = VideoExtensions.includes(extension.toLowerCase())
|
||||||
const isText = !!(
|
const isText = !!(
|
||||||
SpecialTextFiles.find(name => name.toLowerCase() === filename?.toLowerCase()) ||
|
SpecialTextFiles.find(name => name.toLowerCase() === filename?.toLowerCase()) ||
|
||||||
TextExtensions.includes(extension.toLowerCase())
|
TextExtensions.includes(extension.toLowerCase()) ||
|
||||||
|
isSymlink ||
|
||||||
|
isSubmodule
|
||||||
)
|
)
|
||||||
const category = isMarkdown
|
const category = isMarkdown
|
||||||
? FileCategory.MARKDOWN
|
? FileCategory.MARKDOWN
|
||||||
@ -54,12 +66,17 @@ export function useFileContentViewerDecision({
|
|||||||
? FileCategory.AUDIO
|
? FileCategory.AUDIO
|
||||||
: isVideo
|
: isVideo
|
||||||
? FileCategory.VIDEO
|
? FileCategory.VIDEO
|
||||||
|
: isSymlink
|
||||||
|
? FileCategory.SYMLINK
|
||||||
|
: isSubmodule
|
||||||
|
? FileCategory.SUBMODULE
|
||||||
: isText
|
: isText
|
||||||
? FileCategory.TEXT
|
? FileCategory.TEXT
|
||||||
: FileCategory.OTHER
|
: FileCategory.OTHER
|
||||||
const isViewable = isPdf || isSVG || isImage || isAudio || isVideo || isText
|
const isViewable = isPdf || isSVG || isImage || isAudio || isVideo || isText || isSubmodule || isSymlink
|
||||||
const resourceData = resourceContent?.content as RepoFileContent
|
const resourceData = resourceContent?.content as RepoContentExtended
|
||||||
const isFileTooLarge = resourceData?.size !== resourceData?.data_size
|
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}`
|
const rawURL = `/code/api/v1/repos/${repoMetadata?.path}/+/raw/${resourcePath}?routingId=${routingId}&git_ref=${gitRef}`
|
||||||
return {
|
return {
|
||||||
category,
|
category,
|
||||||
@ -73,7 +90,8 @@ export function useFileContentViewerDecision({
|
|||||||
size: resourceData?.size || 0,
|
size: resourceData?.size || 0,
|
||||||
|
|
||||||
// base64 data returned from content API. This snapshot can be truncated by backend
|
// base64 data returned from content API. This snapshot can be truncated by backend
|
||||||
base64Data: resourceData?.data || '',
|
base64Data: resourceData?.data || resourceData?.target || resourceData?.url || '',
|
||||||
|
|
||||||
rawURL
|
rawURL
|
||||||
}
|
}
|
||||||
}, [resourceContent.content]) // eslint-disable-line react-hooks/exhaustive-deps
|
}, [resourceContent.content]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
@ -91,6 +109,8 @@ export enum FileCategory {
|
|||||||
AUDIO = 'AUDIO',
|
AUDIO = 'AUDIO',
|
||||||
VIDEO = 'VIDEO',
|
VIDEO = 'VIDEO',
|
||||||
TEXT = 'TEXT',
|
TEXT = 'TEXT',
|
||||||
|
SYMLINK = 'SYMLINK',
|
||||||
|
SUBMODULE = 'SUBMODULE',
|
||||||
OTHER = 'OTHER'
|
OTHER = 'OTHER'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user