mirror of
https://github.com/harness/drone.git
synced 2025-05-31 11:43:15 +00:00
146 lines
6.0 KiB
TypeScript
146 lines
6.0 KiB
TypeScript
import React, { useMemo, useState } from 'react'
|
|
import { Falsy, Match, Render, Truthy } from 'react-jsx-match'
|
|
import { get } from 'lodash-es'
|
|
import cx from 'classnames'
|
|
import { useHistory } from 'react-router-dom'
|
|
import { Container, Layout, Text, FlexExpander, Button, ButtonVariation, ButtonSize } from '@harnessio/uicore'
|
|
import { Color, FontVariation } from '@harnessio/design-system'
|
|
import { LogViewer } from 'components/LogViewer/LogViewer'
|
|
import { PullRequestCheckType } from 'utils/Utils'
|
|
import { useAppContext } from 'AppContext'
|
|
import { useStrings } from 'framework/strings'
|
|
import { Split } from 'components/Split/Split'
|
|
import { MarkdownViewer } from 'components/MarkdownViewer/MarkdownViewer'
|
|
import type { TypesCheck, TypesStage } from 'services/code'
|
|
import { ExecutionState, ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus'
|
|
import type { ChecksProps } from './ChecksUtils'
|
|
import { CheckPipelineSteps } from './CheckPipelineSteps'
|
|
import { ChecksMenu } from './ChecksMenu'
|
|
import css from './Checks.module.scss'
|
|
|
|
export const Checks: React.FC<ChecksProps> = ({ repoMetadata, pullRequestMetadata, prChecksDecisionResult }) => {
|
|
const { getString } = useStrings()
|
|
const history = useHistory()
|
|
const { routes } = useAppContext()
|
|
const [selectedItemData, setSelectedItemData] = useState<TypesCheck>()
|
|
const [selectedStage, setSelectedStage] = useState<TypesStage | null>(null)
|
|
const isCheckDataMarkdown = useMemo(
|
|
() => selectedItemData?.payload?.kind === PullRequestCheckType.MARKDOWN,
|
|
[selectedItemData?.payload?.kind]
|
|
)
|
|
const logContent = useMemo(
|
|
() => get(selectedItemData, 'payload.data.details', selectedItemData?.summary || ''),
|
|
[selectedItemData]
|
|
)
|
|
const executionLink = useMemo(() => {
|
|
if (selectedStage) {
|
|
return routes.toCODEExecution({
|
|
repoPath: repoMetadata?.path as string,
|
|
pipeline: selectedItemData?.uid as string,
|
|
execution: get(selectedItemData, 'payload.data.execution_number', '')
|
|
})
|
|
} else {
|
|
return selectedItemData?.link
|
|
}
|
|
}, [repoMetadata?.path, routes, selectedItemData, selectedStage])
|
|
|
|
if (!prChecksDecisionResult) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<Container className={css.main}>
|
|
<Match expr={prChecksDecisionResult?.overallStatus}>
|
|
<Truthy>
|
|
<Split
|
|
split="vertical"
|
|
size={'calc(100% - 400px)'}
|
|
minSize={'calc(100% - 300px)'}
|
|
maxSize={'calc(100% - 600px)'}
|
|
primary="second">
|
|
<ChecksMenu
|
|
repoMetadata={repoMetadata}
|
|
pullRequestMetadata={pullRequestMetadata}
|
|
prChecksDecisionResult={prChecksDecisionResult}
|
|
onDataItemChanged={data => {
|
|
setTimeout(() => setSelectedItemData(data), 0)
|
|
}}
|
|
setSelectedStage={setSelectedStage}
|
|
/>
|
|
<Container
|
|
className={cx(css.content, {
|
|
[css.markdown]: isCheckDataMarkdown,
|
|
[css.terminal]: !isCheckDataMarkdown
|
|
})}>
|
|
<Render when={selectedItemData}>
|
|
<Container className={css.header}>
|
|
<Layout.Horizontal className={css.headerLayout} spacing="small">
|
|
<ExecutionStatus
|
|
className={cx(css.status, {
|
|
[css.invert]: selectedItemData?.status === ExecutionState.PENDING
|
|
})}
|
|
status={selectedItemData?.status as ExecutionState}
|
|
iconSize={20}
|
|
noBackground
|
|
iconOnly
|
|
/>
|
|
<Text font={{ variation: FontVariation.BODY1 }} color={Color.WHITE}>
|
|
{selectedItemData?.uid}
|
|
{selectedStage ? ` / ${selectedStage.name}` : ''}
|
|
</Text>
|
|
<FlexExpander />
|
|
<Render when={executionLink}>
|
|
<Button
|
|
className={css.noShrink}
|
|
text={getString('prChecks.viewExternal')}
|
|
rightIcon="chevron-right"
|
|
variation={ButtonVariation.SECONDARY}
|
|
size={ButtonSize.SMALL}
|
|
onClick={() => {
|
|
if (selectedStage) {
|
|
history.push(executionLink as string)
|
|
} else {
|
|
window.open(executionLink, '_blank')
|
|
}
|
|
}}
|
|
/>
|
|
</Render>
|
|
</Layout.Horizontal>
|
|
</Container>
|
|
</Render>
|
|
<Match expr={isCheckDataMarkdown}>
|
|
<Truthy>
|
|
<Container className={css.markdownContainer}>
|
|
<MarkdownViewer darkMode source={logContent} />
|
|
</Container>
|
|
</Truthy>
|
|
<Falsy>
|
|
<Match expr={selectedStage}>
|
|
<Truthy>
|
|
<CheckPipelineSteps
|
|
repoMetadata={repoMetadata}
|
|
pullRequestMetadata={pullRequestMetadata}
|
|
pipelineName={selectedItemData?.uid as string}
|
|
stage={selectedStage as TypesStage}
|
|
executionNumber={get(selectedItemData, 'payload.data.execution_number', '')}
|
|
/>
|
|
</Truthy>
|
|
<Falsy>
|
|
<LogViewer content={logContent} className={css.logViewer} />
|
|
</Falsy>
|
|
</Match>
|
|
</Falsy>
|
|
</Match>
|
|
</Container>
|
|
</Split>
|
|
</Truthy>
|
|
<Falsy>
|
|
<Container flex={{ align: 'center-center' }} height="90%">
|
|
<Text font={{ variation: FontVariation.BODY1 }}>{getString('prChecks.notFound')}</Text>
|
|
</Container>
|
|
</Falsy>
|
|
</Match>
|
|
</Container>
|
|
)
|
|
}
|