mirror of
https://github.com/harness/drone.git
synced 2025-05-17 01:20:13 +08:00
feat: [code-288]: file commit history
This commit is contained in:
parent
8cf58dbde9
commit
24b3ec9fe9
@ -43,7 +43,7 @@
|
|||||||
"@codemirror/state": "^6.2.0",
|
"@codemirror/state": "^6.2.0",
|
||||||
"@codemirror/view": "^6.9.6",
|
"@codemirror/view": "^6.9.6",
|
||||||
"@harness/design-system": "1.4.0",
|
"@harness/design-system": "1.4.0",
|
||||||
"@harness/icons": "1.143.0",
|
"@harness/icons": "1.149.0",
|
||||||
"@harness/ng-tooltip": ">=1.31.25",
|
"@harness/ng-tooltip": ">=1.31.25",
|
||||||
"@harness/telemetry": ">=1.0.42",
|
"@harness/telemetry": ">=1.0.42",
|
||||||
"@harness/uicore": "3.131.1",
|
"@harness/uicore": "3.131.1",
|
||||||
|
@ -44,3 +44,45 @@
|
|||||||
padding-left: var(--spacing-xsmall) !important;
|
padding-left: var(--spacing-xsmall) !important;
|
||||||
padding-right: var(--spacing-xsmall);
|
padding-right: var(--spacing-xsmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fileButton {
|
||||||
|
svg {
|
||||||
|
> path:first-child {
|
||||||
|
fill: unset !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
height: 22px;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--grey-200);
|
||||||
|
background-color: var(--grey-50) !important;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-left: var(--spacing-small) !important;
|
||||||
|
|
||||||
|
&.noCopy {
|
||||||
|
padding-right: var(--spacing-small) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a span {
|
||||||
|
font-size: var(--font-size-small) !important;
|
||||||
|
color: var(--primary-7);
|
||||||
|
font-family: var(--font-family-mono) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
span#commitFileButton {
|
||||||
|
--button-height: 22px !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border-right: 1px solid var(--grey-200) !important;
|
||||||
|
padding-right: 4px !important;
|
||||||
|
padding-bottom: 2px !important ;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button#commitRepoButton {
|
||||||
|
padding-bottom: 2px !important;
|
||||||
|
padding-right: 4px !important;
|
||||||
|
}
|
||||||
|
}
|
@ -7,5 +7,10 @@ declare const styles: {
|
|||||||
readonly rowText: string
|
readonly rowText: string
|
||||||
readonly label: string
|
readonly label: string
|
||||||
readonly refreshIcon: string
|
readonly refreshIcon: string
|
||||||
|
readonly fileButton: string
|
||||||
|
readonly layout: string
|
||||||
|
readonly noCopy: string
|
||||||
|
readonly commitFileButton: string
|
||||||
|
readonly commitRepoButton: string
|
||||||
}
|
}
|
||||||
export default styles
|
export default styles
|
||||||
|
@ -10,18 +10,20 @@ import {
|
|||||||
ButtonSize,
|
ButtonSize,
|
||||||
Button,
|
Button,
|
||||||
FlexExpander,
|
FlexExpander,
|
||||||
StringSubstitute
|
StringSubstitute,
|
||||||
|
Icon,
|
||||||
|
Popover
|
||||||
} from '@harness/uicore'
|
} from '@harness/uicore'
|
||||||
import type { CellProps, Column } from 'react-table'
|
import type { CellProps, Column } from 'react-table'
|
||||||
import { noop, orderBy } from 'lodash-es'
|
import { noop, orderBy } from 'lodash-es'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link, useHistory } from 'react-router-dom'
|
||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import type { TypesCommit } from 'services/code'
|
import type { TypesCommit } from 'services/code'
|
||||||
import { CommitActions } from 'components/CommitActions/CommitActions'
|
import { CommitActions } from 'components/CommitActions/CommitActions'
|
||||||
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
||||||
import { ThreadSection } from 'components/ThreadSection/ThreadSection'
|
import { ThreadSection } from 'components/ThreadSection/ThreadSection'
|
||||||
import { formatDate } from 'utils/Utils'
|
import { FileSection, formatDate } from 'utils/Utils'
|
||||||
import { CodeIcon, GitInfoProps } from 'utils/GitUtils'
|
import { CodeIcon, GitInfoProps } from 'utils/GitUtils'
|
||||||
import type { CODERoutes } from 'RouteDefinitions'
|
import type { CODERoutes } from 'RouteDefinitions'
|
||||||
import css from './CommitsView.module.scss'
|
import css from './CommitsView.module.scss'
|
||||||
@ -32,6 +34,10 @@ interface CommitsViewProps extends Pick<GitInfoProps, 'repoMetadata'> {
|
|||||||
emptyMessage: string
|
emptyMessage: string
|
||||||
prHasChanged?: boolean
|
prHasChanged?: boolean
|
||||||
handleRefresh?: () => void
|
handleRefresh?: () => void
|
||||||
|
showFileHistoryIcons?: boolean
|
||||||
|
gitRef?: string
|
||||||
|
resourcePath?: string
|
||||||
|
setActiveTab?: React.Dispatch<React.SetStateAction<string>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CommitsView({
|
export function CommitsView({
|
||||||
@ -40,8 +46,14 @@ export function CommitsView({
|
|||||||
emptyTitle,
|
emptyTitle,
|
||||||
emptyMessage,
|
emptyMessage,
|
||||||
handleRefresh = noop,
|
handleRefresh = noop,
|
||||||
prHasChanged
|
prHasChanged,
|
||||||
|
showFileHistoryIcons = false,
|
||||||
|
gitRef = '',
|
||||||
|
resourcePath = '',
|
||||||
|
setActiveTab
|
||||||
}: CommitsViewProps) {
|
}: CommitsViewProps) {
|
||||||
|
console.log(repoMetadata, commits, gitRef, resourcePath)
|
||||||
|
const history = useHistory()
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const { routes } = useAppContext()
|
const { routes } = useAppContext()
|
||||||
const columns: Column<TypesCommit>[] = useMemo(
|
const columns: Column<TypesCommit>[] = useMemo(
|
||||||
@ -86,9 +98,66 @@ export function CommitsView({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'buttons',
|
||||||
|
width: showFileHistoryIcons ? '60px' : '0px',
|
||||||
|
Cell: ({ row }: CellProps<TypesCommit>) => {
|
||||||
|
if (showFileHistoryIcons) {
|
||||||
|
return (
|
||||||
|
<Container padding={{ left: 'small' }}>
|
||||||
|
<Layout.Horizontal className={css.layout}>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<Text color={Color.BLACK} padding="medium">
|
||||||
|
{getString('viewFile')}
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
interactionKind="hover">
|
||||||
|
<Icon
|
||||||
|
id={css.commitFileButton}
|
||||||
|
className={css.fileButton}
|
||||||
|
name={'code-content'}
|
||||||
|
size={14}
|
||||||
|
onClick={() => {
|
||||||
|
history.push(
|
||||||
|
routes.toCODERepository({
|
||||||
|
repoPath: repoMetadata.path as string,
|
||||||
|
gitRef: row.original.sha,
|
||||||
|
resourcePath
|
||||||
|
})
|
||||||
|
)
|
||||||
|
if(setActiveTab){
|
||||||
|
setActiveTab(FileSection.CONTENT)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
<Button
|
||||||
|
id={css.commitRepoButton}
|
||||||
|
variation={ButtonVariation.ICON}
|
||||||
|
text={'<>'}
|
||||||
|
onClick={() => {
|
||||||
|
// console.log(gitRef)
|
||||||
|
history.push(
|
||||||
|
routes.toCODERepository({
|
||||||
|
repoPath: repoMetadata.path as string,
|
||||||
|
gitRef: row.original.sha
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
tooltip={getString('viewRepo')}
|
||||||
|
/>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return <Container width={0}></Container>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[repoMetadata, routes]
|
[repoMetadata, routes] // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
)
|
)
|
||||||
const commitsGroupedByDate: Record<string, TypesCommit[]> = useMemo(
|
const commitsGroupedByDate: Record<string, TypesCommit[]> = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
@ -16,7 +16,6 @@ const ImageCarousel = (props: ImageCarouselProps) => {
|
|||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const { isOpen, setIsOpen, setZoomLevel, zoomLevel, imgEvent } = props
|
const { isOpen, setIsOpen, setZoomLevel, zoomLevel, imgEvent } = props
|
||||||
const [imgTitle, setImageTitle] = useState(imgEvent[0])
|
const [imgTitle, setImageTitle] = useState(imgEvent[0])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
portalClassName={css.portalContainer}
|
portalClassName={css.portalContainer}
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
&.hideGutter > ::before {
|
&.hideGutter > ::before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
&.hideTitleGutter > ::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +41,10 @@
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
&.hideTitleGutter > ::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.inCommentBox {
|
.inCommentBox {
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
@ -79,5 +86,8 @@
|
|||||||
&.hideGutter > ::before {
|
&.hideGutter > ::before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
&.hideTitleGutter > ::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ declare const styles: {
|
|||||||
readonly thread: string
|
readonly thread: string
|
||||||
readonly content: string
|
readonly content: string
|
||||||
readonly hideGutter: string
|
readonly hideGutter: string
|
||||||
|
readonly hideTitleGutter: string
|
||||||
readonly titleContent: string
|
readonly titleContent: string
|
||||||
readonly inCommentBox: string
|
readonly inCommentBox: string
|
||||||
readonly threadLessSpace: string
|
readonly threadLessSpace: string
|
||||||
|
@ -8,6 +8,7 @@ interface ThreadSectionProps {
|
|||||||
className?: string
|
className?: string
|
||||||
contentClassName?: string
|
contentClassName?: string
|
||||||
hideGutter?: boolean
|
hideGutter?: boolean
|
||||||
|
hideTitleGutter?: boolean
|
||||||
onlyTitle?: boolean
|
onlyTitle?: boolean
|
||||||
inCommentBox?: boolean
|
inCommentBox?: boolean
|
||||||
lastItem?: boolean
|
lastItem?: boolean
|
||||||
@ -19,13 +20,14 @@ export const ThreadSection: React.FC<ThreadSectionProps> = ({
|
|||||||
className,
|
className,
|
||||||
contentClassName,
|
contentClassName,
|
||||||
hideGutter,
|
hideGutter,
|
||||||
|
hideTitleGutter,
|
||||||
onlyTitle,
|
onlyTitle,
|
||||||
inCommentBox = false,
|
inCommentBox = false,
|
||||||
lastItem
|
lastItem
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
className={cx(inCommentBox ? css.thread : css.threadLessSpace, className, {
|
className={cx(inCommentBox ? css.thread : css.threadLessSpace,hideTitleGutter ? css.hideTitleGutter : '', className, {
|
||||||
[css.titleContent]: onlyTitle && !inCommentBox && !lastItem,
|
[css.titleContent]: onlyTitle && !inCommentBox && !lastItem,
|
||||||
[css.inCommentBox]: inCommentBox && !lastItem
|
[css.inCommentBox]: inCommentBox && !lastItem
|
||||||
})}>
|
})}>
|
||||||
|
@ -140,6 +140,7 @@ export interface StringsMap {
|
|||||||
generateCloneText: string
|
generateCloneText: string
|
||||||
getMyCloneTitle: string
|
getMyCloneTitle: string
|
||||||
gitIgnore: string
|
gitIgnore: string
|
||||||
|
hideCommitHistory: string
|
||||||
history: string
|
history: string
|
||||||
in: string
|
in: string
|
||||||
inactiveBranches: string
|
inactiveBranches: string
|
||||||
@ -316,6 +317,7 @@ export interface StringsMap {
|
|||||||
selectBranchPlaceHolder: string
|
selectBranchPlaceHolder: string
|
||||||
selectToViewMore: string
|
selectToViewMore: string
|
||||||
settings: string
|
settings: string
|
||||||
|
showCommitHistory: string
|
||||||
showEverything: string
|
showEverything: string
|
||||||
signIn: string
|
signIn: string
|
||||||
signUp: string
|
signUp: string
|
||||||
@ -348,8 +350,10 @@ export interface StringsMap {
|
|||||||
viewAllBranches: string
|
viewAllBranches: string
|
||||||
viewAllTags: string
|
viewAllTags: string
|
||||||
viewCommitDetails: string
|
viewCommitDetails: string
|
||||||
|
viewFile: string
|
||||||
viewFiles: string
|
viewFiles: string
|
||||||
viewRaw: string
|
viewRaw: string
|
||||||
|
viewRepo: string
|
||||||
viewed: string
|
viewed: string
|
||||||
webhook: string
|
webhook: string
|
||||||
webhookAllEventsSelected: string
|
webhookAllEventsSelected: string
|
||||||
|
@ -417,3 +417,7 @@ tagger: Tagger
|
|||||||
confirmDelete: Confirm delete
|
confirmDelete: Confirm delete
|
||||||
tagEmpty: Here is no Tag. Try to
|
tagEmpty: Here is no Tag. Try to
|
||||||
newTag: New Tag
|
newTag: New Tag
|
||||||
|
viewFile: View the file at this point in the history
|
||||||
|
viewRepo: View the repository at this point in the history
|
||||||
|
hideCommitHistory: Hide Rename History for {{file}}
|
||||||
|
showCommitHistory: Show Rename History for {{file}}
|
||||||
|
@ -65,7 +65,7 @@ export const Conversation: React.FC<ConversationProps> = ({
|
|||||||
// Determine all parent activities
|
// Determine all parent activities
|
||||||
const parentActivities = orderBy(
|
const parentActivities = orderBy(
|
||||||
activities?.filter(activity => !activity.parent_id) || [],
|
activities?.filter(activity => !activity.parent_id) || [],
|
||||||
'edited',
|
'created',
|
||||||
dateOrderSort
|
dateOrderSort
|
||||||
).map(_comment => [_comment])
|
).map(_comment => [_comment])
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import { EmptyRepositoryInfo } from './EmptyRepositoryInfo'
|
|||||||
import css from './Repository.module.scss'
|
import css from './Repository.module.scss'
|
||||||
|
|
||||||
export default function Repository() {
|
export default function Repository() {
|
||||||
const { gitRef, resourcePath, repoMetadata, error, loading, refetch } = useGetRepositoryMetadata()
|
const { gitRef, resourcePath, repoMetadata, error, loading, refetch, commitRef } = useGetRepositoryMetadata()
|
||||||
const {
|
const {
|
||||||
data: resourceContent,
|
data: resourceContent,
|
||||||
error: resourceError,
|
error: resourceError,
|
||||||
@ -82,6 +82,7 @@ export default function Repository() {
|
|||||||
gitRef={gitRef}
|
gitRef={gitRef}
|
||||||
resourcePath={resourcePath}
|
resourcePath={resourcePath}
|
||||||
resourceContent={resourceContent}
|
resourceContent={resourceContent}
|
||||||
|
commitRef={commitRef}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
padding: var(--spacing-xlarge) !important;
|
padding: var(--spacing-xlarge) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gitHistory {
|
||||||
|
padding: var(--spacing-small) var(--spacing-xlarge) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.tabsContainer {
|
.tabsContainer {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -6,6 +6,7 @@ declare const styles: {
|
|||||||
readonly content: string
|
readonly content: string
|
||||||
readonly fileContent: string
|
readonly fileContent: string
|
||||||
readonly gitBlame: string
|
readonly gitBlame: string
|
||||||
|
readonly gitHistory: string
|
||||||
readonly tabsContainer: string
|
readonly tabsContainer: string
|
||||||
readonly tabTitle: string
|
readonly tabTitle: string
|
||||||
readonly count: string
|
readonly count: string
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
|
import { useGet } from 'restful-react'
|
||||||
import {
|
import {
|
||||||
ButtonSize,
|
ButtonSize,
|
||||||
ButtonVariation,
|
ButtonVariation,
|
||||||
@ -13,7 +14,7 @@ import {
|
|||||||
import { Render } from 'react-jsx-match'
|
import { Render } from 'react-jsx-match'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
import { SourceCodeViewer } from 'components/SourceCodeViewer/SourceCodeViewer'
|
import { SourceCodeViewer } from 'components/SourceCodeViewer/SourceCodeViewer'
|
||||||
import type { OpenapiContentInfo, RepoFileContent } from 'services/code'
|
import type { OpenapiContentInfo, RepoFileContent, TypesCommit } from 'services/code'
|
||||||
import {
|
import {
|
||||||
decodeGitContent,
|
decodeGitContent,
|
||||||
findMarkdownInfo,
|
findMarkdownInfo,
|
||||||
@ -22,33 +23,34 @@ import {
|
|||||||
isRefATag,
|
isRefATag,
|
||||||
makeDiffRefs
|
makeDiffRefs
|
||||||
} from 'utils/GitUtils'
|
} from 'utils/GitUtils'
|
||||||
import { filenameToLanguage, permissionProps } from 'utils/Utils'
|
import { filenameToLanguage, permissionProps, LIST_FETCHING_LIMIT, RenameDetails, FileSection } from 'utils/Utils'
|
||||||
import { useAppContext } from 'AppContext'
|
import { useAppContext } from 'AppContext'
|
||||||
import { LatestCommitForFile } from 'components/LatestCommit/LatestCommit'
|
import { LatestCommitForFile } from 'components/LatestCommit/LatestCommit'
|
||||||
import { useCommitModal } from 'components/CommitModalButton/CommitModalButton'
|
import { useCommitModal } from 'components/CommitModalButton/CommitModalButton'
|
||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButton'
|
import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButton'
|
||||||
import { PlainButton } from 'components/PlainButton/PlainButton'
|
import { PlainButton } from 'components/PlainButton/PlainButton'
|
||||||
|
import { CommitsView } from 'components/CommitsView/CommitsView'
|
||||||
|
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
||||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||||
|
import { usePageIndex } from 'hooks/usePageIndex'
|
||||||
import { Readme } from '../FolderContent/Readme'
|
import { Readme } from '../FolderContent/Readme'
|
||||||
import { GitBlame } from './GitBlame'
|
import { GitBlame } from './GitBlame'
|
||||||
|
import RenameContentHistory from './RenameContentHistory'
|
||||||
import css from './FileContent.module.scss'
|
import css from './FileContent.module.scss'
|
||||||
|
|
||||||
enum FileSection {
|
|
||||||
CONTENT = 'content',
|
|
||||||
BLAME = 'blame',
|
|
||||||
HISTORY = 'history'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function FileContent({
|
export function FileContent({
|
||||||
repoMetadata,
|
repoMetadata,
|
||||||
gitRef,
|
gitRef,
|
||||||
resourcePath,
|
resourcePath,
|
||||||
resourceContent
|
resourceContent,
|
||||||
}: Pick<GitInfoProps, 'repoMetadata' | 'gitRef' | 'resourcePath' | 'resourceContent'>) {
|
commitRef
|
||||||
|
}: Pick<GitInfoProps, 'repoMetadata' | 'gitRef' | 'resourcePath' | 'resourceContent' | 'commitRef'>) {
|
||||||
const { routes } = useAppContext()
|
const { routes } = useAppContext()
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
const [activeTab, setActiveTab] = React.useState<string>(FileSection.CONTENT)
|
||||||
|
|
||||||
const content = useMemo(
|
const content = useMemo(
|
||||||
() => decodeGitContent((resourceContent?.content as RepoFileContent)?.data),
|
() => decodeGitContent((resourceContent?.content as RepoFileContent)?.data),
|
||||||
[resourceContent?.content]
|
[resourceContent?.content]
|
||||||
@ -105,13 +107,27 @@ export function FileContent({
|
|||||||
}
|
}
|
||||||
return { disabled: isRefATag(gitRef) || false, tooltip: undefined }
|
return { disabled: isRefATag(gitRef) || false, tooltip: undefined }
|
||||||
}, [permPushResult, gitRef]) // eslint-disable-line react-hooks/exhaustive-deps
|
}, [permPushResult, gitRef]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
const [page, setPage] = usePageIndex()
|
||||||
|
const { data: commits, response } = useGet<{ commits: TypesCommit[]; rename_details: RenameDetails[] }>({
|
||||||
|
path: `/api/v1/repos/${repoMetadata?.path}/+/commitsV2`,
|
||||||
|
queryParams: {
|
||||||
|
limit: LIST_FETCHING_LIMIT,
|
||||||
|
page,
|
||||||
|
git_ref: commitRef || repoMetadata?.default_branch,
|
||||||
|
path: resourcePath
|
||||||
|
},
|
||||||
|
lazy: !repoMetadata
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={css.tabsContainer}>
|
<Container className={css.tabsContainer}>
|
||||||
<Tabs
|
<Tabs
|
||||||
id="fileTabs"
|
id="fileTabs"
|
||||||
|
selectedTabId={activeTab}
|
||||||
defaultSelectedTabId={FileSection.CONTENT}
|
defaultSelectedTabId={FileSection.CONTENT}
|
||||||
large={false}
|
large={false}
|
||||||
|
onChange={(id: string) => setActiveTab(id)}
|
||||||
tabList={[
|
tabList={[
|
||||||
{
|
{
|
||||||
id: FileSection.CONTENT,
|
id: FileSection.CONTENT,
|
||||||
@ -233,6 +249,38 @@ export function FileContent({
|
|||||||
))}
|
))}
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: FileSection.HISTORY,
|
||||||
|
title: getString('history'),
|
||||||
|
panel: (
|
||||||
|
<>
|
||||||
|
{repoMetadata && !!commits?.commits?.length && (
|
||||||
|
<>
|
||||||
|
<Container className={css.gitBlame}>
|
||||||
|
<CommitsView
|
||||||
|
commits={commits.commits}
|
||||||
|
repoMetadata={repoMetadata}
|
||||||
|
emptyTitle={getString('noCommits')}
|
||||||
|
emptyMessage={getString('noCommitsMessage')}
|
||||||
|
showFileHistoryIcons={true}
|
||||||
|
gitRef={gitRef}
|
||||||
|
resourcePath={resourcePath}
|
||||||
|
setActiveTab={setActiveTab}
|
||||||
|
/>
|
||||||
|
{/* <ThreadSection></ThreadSection> */}
|
||||||
|
|
||||||
|
<ResourceListingPagination response={response} page={page} setPage={setPage} />
|
||||||
|
</Container>
|
||||||
|
<Container className={css.gitHistory}>
|
||||||
|
{commits?.rename_details && repoMetadata ? (
|
||||||
|
<RenameContentHistory rename_details={commits.rename_details} repoMetadata={repoMetadata} />
|
||||||
|
) : null}
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
.contentSection {
|
||||||
|
padding-left: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hideText {
|
||||||
|
text-align: center !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
7
web/src/pages/Repository/RepositoryContent/FileContent/RenameContentHistory.module.scss.d.ts
vendored
Normal file
7
web/src/pages/Repository/RepositoryContent/FileContent/RenameContentHistory.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// this is an auto-generated file
|
||||||
|
declare const styles: {
|
||||||
|
readonly contentSection: string
|
||||||
|
readonly hideText: string
|
||||||
|
}
|
||||||
|
export default styles
|
@ -0,0 +1,99 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import { Text } from '@harness/uicore'
|
||||||
|
import { useGet } from 'restful-react'
|
||||||
|
import { ThreadSection } from 'components/ThreadSection/ThreadSection'
|
||||||
|
import { LIST_FETCHING_LIMIT, RenameDetails } from 'utils/Utils'
|
||||||
|
import { usePageIndex } from 'hooks/usePageIndex'
|
||||||
|
import type { TypesCommit, TypesRepository } from 'services/code'
|
||||||
|
import { useStrings } from 'framework/strings'
|
||||||
|
import { CommitsView } from 'components/CommitsView/CommitsView'
|
||||||
|
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
||||||
|
|
||||||
|
import css from './RenameContentHistory.module.scss'
|
||||||
|
|
||||||
|
const RenameContentHistory = (props: { rename_details: RenameDetails[], repoMetadata: TypesRepository, fileVisibility?: { [key: string]: boolean } }) => {
|
||||||
|
const { rename_details, repoMetadata, fileVisibility: initialFileVisibility } = props;
|
||||||
|
const { getString } = useStrings();
|
||||||
|
const [fileVisibility, setFileVisibility] = useState(initialFileVisibility || {});
|
||||||
|
const [page, setPage] = usePageIndex();
|
||||||
|
const { data: commits, response, refetch: getCommitHistory } = useGet<{ commits: TypesCommit[]; rename_details: RenameDetails[] }>({
|
||||||
|
path: `/api/v1/repos/${repoMetadata?.path}/+/commitsV2`,
|
||||||
|
lazy: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleCommitHistory = async (details: RenameDetails) => {
|
||||||
|
setFileVisibility(prevVisibility => ({
|
||||||
|
...prevVisibility,
|
||||||
|
[details.old_path]: !prevVisibility[details.old_path]
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!fileVisibility[details.old_path]) {
|
||||||
|
await getCommitHistory({
|
||||||
|
queryParams: {
|
||||||
|
limit: LIST_FETCHING_LIMIT,
|
||||||
|
page,
|
||||||
|
git_ref: details.commit_sha_before,
|
||||||
|
path: details.old_path
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{rename_details.map((details, index) => {
|
||||||
|
const isFileShown = fileVisibility[details.old_path];
|
||||||
|
const commitsData = commits?.commits;
|
||||||
|
const showCommitHistory = isFileShown && commitsData && commitsData.length > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThreadSection
|
||||||
|
key={index}
|
||||||
|
hideGutter
|
||||||
|
hideTitleGutter
|
||||||
|
contentClassName={css.contentSection}
|
||||||
|
title={
|
||||||
|
<Text
|
||||||
|
hidden={showCommitHistory}
|
||||||
|
className={css.hideText}
|
||||||
|
padding={{top:"large"}}
|
||||||
|
onClick={() => toggleCommitHistory(details)}
|
||||||
|
>
|
||||||
|
{showCommitHistory ?getString('hideCommitHistory',{file:details.old_path}) :getString('showCommitHistory',{file:details.old_path})}
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
onlyTitle={showCommitHistory}
|
||||||
|
>
|
||||||
|
{showCommitHistory && (
|
||||||
|
<>
|
||||||
|
<CommitsView
|
||||||
|
commits={commits.commits}
|
||||||
|
repoMetadata={repoMetadata}
|
||||||
|
emptyTitle={getString('noCommits')}
|
||||||
|
emptyMessage={getString('noCommitsMessage')}
|
||||||
|
showFileHistoryIcons={true}
|
||||||
|
resourcePath={details.old_path}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
className={css.hideText}
|
||||||
|
padding={{ left: 'xxxlarge', right: 'xxxlarge', top: 'large' }}
|
||||||
|
onClick={() => toggleCommitHistory(details)}
|
||||||
|
>
|
||||||
|
{getString('hideCommitHistory',{file:details.old_path})}
|
||||||
|
</Text>
|
||||||
|
<ResourceListingPagination response={response} page={page} setPage={setPage} />
|
||||||
|
<RenameContentHistory
|
||||||
|
rename_details={commits.rename_details.filter(file => file.old_path !== details.old_path)}
|
||||||
|
repoMetadata={repoMetadata}
|
||||||
|
fileVisibility={fileVisibility}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</ThreadSection>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RenameContentHistory;
|
@ -10,8 +10,9 @@ export function RepositoryContent({
|
|||||||
repoMetadata,
|
repoMetadata,
|
||||||
gitRef,
|
gitRef,
|
||||||
resourcePath,
|
resourcePath,
|
||||||
resourceContent
|
resourceContent,
|
||||||
}: Pick<GitInfoProps, 'repoMetadata' | 'gitRef' | 'resourcePath' | 'resourceContent'>) {
|
commitRef
|
||||||
|
}: Pick<GitInfoProps, 'repoMetadata' | 'gitRef' | 'resourcePath' | 'resourceContent' | 'commitRef' >) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.scroll({ top: 0 })
|
window.scroll({ top: 0 })
|
||||||
}, [gitRef, resourcePath])
|
}, [gitRef, resourcePath])
|
||||||
@ -36,6 +37,7 @@ export function RepositoryContent({
|
|||||||
gitRef={gitRef}
|
gitRef={gitRef}
|
||||||
resourcePath={resourcePath}
|
resourcePath={resourcePath}
|
||||||
resourceContent={resourceContent}
|
resourceContent={resourceContent}
|
||||||
|
commitRef={commitRef}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -47,6 +47,13 @@ export interface PageBrowserProps {
|
|||||||
page: string
|
page: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RenameDetails {
|
||||||
|
commit_sha_after: string
|
||||||
|
commit_sha_before: string
|
||||||
|
new_path: string
|
||||||
|
old_path: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface SourceCodeEditorProps {
|
export interface SourceCodeEditorProps {
|
||||||
source: string
|
source: string
|
||||||
language?: string
|
language?: string
|
||||||
@ -135,6 +142,12 @@ export enum CodeCommentState {
|
|||||||
RESOLVED = 'resolved'
|
RESOLVED = 'resolved'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum FileSection {
|
||||||
|
CONTENT = 'content',
|
||||||
|
BLAME = 'blame',
|
||||||
|
HISTORY = 'history'
|
||||||
|
}
|
||||||
|
|
||||||
const MONACO_SUPPORTED_LANGUAGES = [
|
const MONACO_SUPPORTED_LANGUAGES = [
|
||||||
'abap',
|
'abap',
|
||||||
'apex',
|
'apex',
|
||||||
|
@ -686,10 +686,10 @@
|
|||||||
resolved "https://npm.pkg.github.com/download/@harness/design-system/1.4.0/b2a77f73696d71a53765c71efd0a5b28039fa1cf#b2a77f73696d71a53765c71efd0a5b28039fa1cf"
|
resolved "https://npm.pkg.github.com/download/@harness/design-system/1.4.0/b2a77f73696d71a53765c71efd0a5b28039fa1cf#b2a77f73696d71a53765c71efd0a5b28039fa1cf"
|
||||||
integrity sha512-LuzuPEHPkE6xgIuXxn16RCCvPY1NDXF3o1JWlIjxmepoDTkgFuwnV1OhBdQftvAVBawJ5wJP10IIKUL161LdYg==
|
integrity sha512-LuzuPEHPkE6xgIuXxn16RCCvPY1NDXF3o1JWlIjxmepoDTkgFuwnV1OhBdQftvAVBawJ5wJP10IIKUL161LdYg==
|
||||||
|
|
||||||
"@harness/icons@1.143.0":
|
"@harness/icons@1.149.0":
|
||||||
version "1.143.0"
|
version "1.149.0"
|
||||||
resolved "https://npm.pkg.github.com/download/@harness/icons/1.143.0/fb412c51530b7d113694738bfa682db8e141d169#fb412c51530b7d113694738bfa682db8e141d169"
|
resolved "https://npm.pkg.github.com/download/@harness/icons/1.149.0/0f2e1faba8d5e1a651b5b8f2c03582d30702d81f#0f2e1faba8d5e1a651b5b8f2c03582d30702d81f"
|
||||||
integrity sha512-RfIcmJkc7vXWCAHVti07Zc54FMxu54uPW77SkEL9IbRhxM8qEof9Jmcgq7CsEfHTHlCk2+oFeXQKsCFZjv34SA==
|
integrity sha512-kfcGY7t+V1NoSRAoDJofZpKAY79UN+NI8XWf0OLYtRI1JnVF37ZyJgvJ3Vk4VgLbMElsPRXopcx9ADjCWz/RZw==
|
||||||
|
|
||||||
"@harness/jarvis@^0.12.0":
|
"@harness/jarvis@^0.12.0":
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user