mirror of
https://github.com/harness/drone.git
synced 2025-05-19 02:20:03 +08:00
Merge branch 'Pipelines-list-improve' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#391)
This commit is contained in:
commit
2ae31d4337
@ -9,7 +9,6 @@
|
||||
.log {
|
||||
color: white;
|
||||
font-family: Inconsolata, monospace;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
|
@ -1,16 +1,16 @@
|
||||
.logLayout {
|
||||
margin-left: 2.3rem !important;
|
||||
margin-left: var(--spacing-xxxlarge) !important;
|
||||
}
|
||||
|
||||
.lineNumber {
|
||||
width: 1.5rem;
|
||||
width: var(--spacing-xlarge);
|
||||
color: #999;
|
||||
margin-right: 1rem;
|
||||
margin-right: 16px;
|
||||
font-family: 'Roboto Mono' !important;
|
||||
}
|
||||
|
||||
.log {
|
||||
color: white !important;
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: var(--spacing-medium);
|
||||
font-family: 'Roboto Mono' !important;
|
||||
}
|
||||
|
@ -5,6 +5,5 @@
|
||||
}
|
||||
|
||||
.loading {
|
||||
margin-left: 2.3rem !important;
|
||||
margin-top: 1.5rem !important;
|
||||
margin-left: var(--spacing-xxxlarge) !important;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
height: 100%;
|
||||
|
||||
.menuItem {
|
||||
margin: 0.5rem 0 0.5rem 1rem !important;
|
||||
margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-medium) !important;
|
||||
cursor: pointer;
|
||||
|
||||
&:not(:last-child) {
|
||||
@ -35,8 +35,12 @@
|
||||
.uid {
|
||||
color: var(--grey-700) !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 1rem !important;
|
||||
font-size: var(--font-size-normal) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.statusIcon {
|
||||
align-self: center !important;
|
||||
}
|
||||
|
@ -7,5 +7,6 @@ declare const styles: {
|
||||
readonly layout: string
|
||||
readonly selected: string
|
||||
readonly uid: string
|
||||
readonly statusIcon: string
|
||||
}
|
||||
export default styles
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { FC } from 'react'
|
||||
import { Container, Layout, Text } from '@harnessio/uicore'
|
||||
import { Icon } from '@harnessio/icons'
|
||||
import cx from 'classnames'
|
||||
import type { TypesStage } from 'services/code'
|
||||
import { ExecutionState, ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
import { getStatus } from 'utils/PipelineUtils'
|
||||
import css from './ExecutionStageList.module.scss'
|
||||
|
||||
interface ExecutionStageListProps {
|
||||
@ -26,7 +27,13 @@ const ExecutionStage: FC<ExecutionStageProps> = ({ stage, isSelected = false, se
|
||||
setSelectedStage(stage.number || null)
|
||||
}}>
|
||||
<Layout.Horizontal spacing="small" className={cx(css.layout, { [css.selected]: isSelected })}>
|
||||
<Icon name="success-tick" size={16} />
|
||||
<ExecutionStatus
|
||||
status={getStatus(stage.status || ExecutionState.PENDING)}
|
||||
iconOnly
|
||||
noBackground
|
||||
iconSize={16}
|
||||
className={css.statusIcon}
|
||||
/>
|
||||
<Text className={css.uid} lineClamp={1}>
|
||||
{stage.name}
|
||||
</Text>
|
||||
|
@ -3,9 +3,9 @@ import { Text } from '@harnessio/uicore'
|
||||
import type { IconName } from '@harnessio/icons'
|
||||
import cx from 'classnames'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import css from './PRCheckExecutionStatus.module.scss'
|
||||
import css from './ExecutionStatus.module.scss'
|
||||
|
||||
export enum PRCheckExecutionState {
|
||||
export enum ExecutionState {
|
||||
PENDING = 'pending',
|
||||
RUNNING = 'running',
|
||||
SUCCESS = 'success',
|
||||
@ -13,15 +13,15 @@ export enum PRCheckExecutionState {
|
||||
ERROR = 'error'
|
||||
}
|
||||
|
||||
interface PRCheckExecutionStatusProps {
|
||||
status: PRCheckExecutionState
|
||||
interface ExecutionStatusProps {
|
||||
status: ExecutionState
|
||||
iconOnly?: boolean
|
||||
noBackground?: boolean
|
||||
iconSize?: number
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const PRCheckExecutionStatus: React.FC<PRCheckExecutionStatusProps> = ({
|
||||
export const ExecutionStatus: React.FC<ExecutionStatusProps> = ({
|
||||
status,
|
||||
iconSize = 20,
|
||||
iconOnly = false,
|
||||
@ -31,27 +31,27 @@ export const PRCheckExecutionStatus: React.FC<PRCheckExecutionStatusProps> = ({
|
||||
const { getString } = useStrings()
|
||||
const maps = useMemo(
|
||||
() => ({
|
||||
[PRCheckExecutionState.PENDING]: {
|
||||
[ExecutionState.PENDING]: {
|
||||
icon: 'ci-pending-build',
|
||||
css: css.pending,
|
||||
title: getString('pending').toLocaleUpperCase()
|
||||
},
|
||||
[PRCheckExecutionState.RUNNING]: {
|
||||
[ExecutionState.RUNNING]: {
|
||||
icon: 'running-filled',
|
||||
css: css.running,
|
||||
title: getString('running').toLocaleUpperCase()
|
||||
},
|
||||
[PRCheckExecutionState.SUCCESS]: {
|
||||
[ExecutionState.SUCCESS]: {
|
||||
icon: 'execution-success',
|
||||
css: css.success,
|
||||
title: getString('success').toLocaleUpperCase()
|
||||
},
|
||||
[PRCheckExecutionState.FAILURE]: {
|
||||
[ExecutionState.FAILURE]: {
|
||||
icon: 'error-transparent-no-outline',
|
||||
css: css.failure,
|
||||
title: getString('failed').toLocaleUpperCase()
|
||||
},
|
||||
[PRCheckExecutionState.ERROR]: {
|
||||
[ExecutionState.ERROR]: {
|
||||
icon: 'solid-error',
|
||||
css: css.error,
|
||||
title: getString('error').toLocaleUpperCase()
|
@ -314,9 +314,11 @@ export interface StringsMap {
|
||||
payloadUrl: string
|
||||
payloadUrlLabel: string
|
||||
pending: string
|
||||
'pipelines.lastExecution': string
|
||||
'pipelines.name': string
|
||||
'pipelines.newPipelineButton': string
|
||||
'pipelines.noData': string
|
||||
'pipelines.time': string
|
||||
'pr.ableToMerge': string
|
||||
'pr.addDescription': string
|
||||
'pr.authorCommentedPR': string
|
||||
|
@ -4,7 +4,7 @@ import { Color } from '@harnessio/design-system'
|
||||
import type { GitInfoProps } from 'utils/GitUtils'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { useListStatusCheckResults } from 'services/code'
|
||||
import { PRCheckExecutionState } from 'components/PRCheckExecutionStatus/PRCheckExecutionStatus'
|
||||
import { ExecutionState } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
|
||||
export function usePRChecksDecision({
|
||||
repoMetadata,
|
||||
@ -22,18 +22,18 @@ export function usePRChecksDecision({
|
||||
const [message, setMessage] = useState('')
|
||||
const [complete, setComplete] = useState(true)
|
||||
const status = useMemo(() => {
|
||||
let _status: PRCheckExecutionState | undefined
|
||||
let _status: ExecutionState | undefined
|
||||
const _count = { ...DEFAULT_COUNTS }
|
||||
const total = data?.length
|
||||
|
||||
if (total) {
|
||||
for (const check of data) {
|
||||
switch (check.status) {
|
||||
case PRCheckExecutionState.ERROR:
|
||||
case PRCheckExecutionState.FAILURE:
|
||||
case PRCheckExecutionState.RUNNING:
|
||||
case PRCheckExecutionState.PENDING:
|
||||
case PRCheckExecutionState.SUCCESS:
|
||||
case ExecutionState.ERROR:
|
||||
case ExecutionState.FAILURE:
|
||||
case ExecutionState.RUNNING:
|
||||
case ExecutionState.PENDING:
|
||||
case ExecutionState.SUCCESS:
|
||||
_count[check.status]++
|
||||
setCount({ ..._count })
|
||||
break
|
||||
@ -44,27 +44,27 @@ export function usePRChecksDecision({
|
||||
}
|
||||
|
||||
if (_count.error) {
|
||||
_status = PRCheckExecutionState.ERROR
|
||||
_status = ExecutionState.ERROR
|
||||
setColor(Color.RED_900)
|
||||
setBackground(Color.RED_50)
|
||||
setMessage(stringSubstitute(getString('prChecks.error'), { count: _count.error, total }) as string)
|
||||
} else if (_count.failure) {
|
||||
_status = PRCheckExecutionState.FAILURE
|
||||
_status = ExecutionState.FAILURE
|
||||
setColor(Color.RED_900)
|
||||
setBackground(Color.RED_50)
|
||||
setMessage(stringSubstitute(getString('prChecks.failure'), { count: _count.failure, total }) as string)
|
||||
} else if (_count.running) {
|
||||
_status = PRCheckExecutionState.RUNNING
|
||||
_status = ExecutionState.RUNNING
|
||||
setColor(Color.ORANGE_900)
|
||||
setBackground(Color.ORANGE_100)
|
||||
setMessage(stringSubstitute(getString('prChecks.running'), { count: _count.running, total }) as string)
|
||||
} else if (_count.pending) {
|
||||
_status = PRCheckExecutionState.PENDING
|
||||
_status = ExecutionState.PENDING
|
||||
setColor(Color.GREY_600)
|
||||
setBackground(Color.GREY_100)
|
||||
setMessage(stringSubstitute(getString('prChecks.pending'), { count: _count.pending, total }) as string)
|
||||
} else if (_count.success) {
|
||||
_status = PRCheckExecutionState.SUCCESS
|
||||
_status = ExecutionState.SUCCESS
|
||||
setColor(Color.GREEN_800)
|
||||
setBackground(Color.GREEN_50)
|
||||
setMessage(stringSubstitute(getString('prChecks.success'), { count: _count.success, total }) as string)
|
||||
|
@ -624,6 +624,8 @@ pipelines:
|
||||
noData: There are no pipelines :(
|
||||
newPipelineButton: New Pipeline
|
||||
name: Pipeline Name
|
||||
time: Time
|
||||
lastExecution: Last Execution
|
||||
executions:
|
||||
noData: There are no executions :(
|
||||
newExecutionButton: Run Pipeline
|
||||
|
@ -7,25 +7,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
[class*='TableV2--header'] [class*='variation-table-headers'] {
|
||||
text-transform: none;
|
||||
color: var(--grey-400);
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.row {
|
||||
height: 80px;
|
||||
box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.08), 0px 0.5px 2px rgba(96, 97, 112, 0.16);
|
||||
overflow: hidden;
|
||||
|
||||
&.noDesc > div {
|
||||
height: 44px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.withError {
|
||||
display: grid;
|
||||
}
|
||||
@ -61,35 +42,30 @@
|
||||
|
||||
.number {
|
||||
color: var(--grey-400) !important;
|
||||
font-size: 0.875rem !important;
|
||||
font-size: var(--font-size-normal) !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: var(--grey-800) !important;
|
||||
font-size: 0.875rem !important;
|
||||
font-size: var(--font-size-normal) !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.author {
|
||||
color: var(--grey500) !important;
|
||||
font-size: 0.6875rem !important;
|
||||
font-size: var(--font-size-small) !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.hash {
|
||||
color: var(--primary-7) !important;
|
||||
font-family: Roboto Mono !important;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
font-size: var(--font-size-small) !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.triggerLayout {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.divider {
|
||||
color: var(--grey-300) !important;
|
||||
font-size: 0.25rem !important;
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,6 @@
|
||||
declare const styles: {
|
||||
readonly main: string
|
||||
readonly layout: string
|
||||
readonly table: string
|
||||
readonly row: string
|
||||
readonly noDesc: string
|
||||
readonly withError: string
|
||||
readonly nameContainer: string
|
||||
readonly name: string
|
||||
@ -15,6 +12,5 @@ declare const styles: {
|
||||
readonly author: string
|
||||
readonly hash: string
|
||||
readonly triggerLayout: string
|
||||
readonly divider: string
|
||||
}
|
||||
export default styles
|
||||
|
@ -16,7 +16,6 @@ import cx from 'classnames'
|
||||
import type { CellProps, Column } from 'react-table'
|
||||
import { useHistory, useParams } from 'react-router-dom'
|
||||
import { useGet } from 'restful-react'
|
||||
import { Icon } from '@harnessio/icons'
|
||||
import { Timer, Calendar } from 'iconoir-react'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||
@ -30,6 +29,9 @@ import { usePageIndex } from 'hooks/usePageIndex'
|
||||
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
||||
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
||||
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
|
||||
import { ExecutionState, ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
import { getStatus } from 'utils/PipelineUtils'
|
||||
import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator'
|
||||
import noExecutionImage from '../RepositoriesListing/no-repo.svg'
|
||||
import css from './ExecutionList.module.scss'
|
||||
|
||||
@ -71,11 +73,14 @@ const ExecutionList = () => {
|
||||
Cell: ({ row }: CellProps<TypesExecution>) => {
|
||||
const record = row.original
|
||||
return (
|
||||
<Container className={css.nameContainer}>
|
||||
<Layout.Vertical>
|
||||
<Layout.Vertical className={css.nameContainer}>
|
||||
<Layout.Horizontal spacing={'small'} style={{ alignItems: 'center' }}>
|
||||
{/* TODO this icon need to depend on the status */}
|
||||
<Icon name="success-tick" size={18} />
|
||||
<ExecutionStatus
|
||||
status={getStatus(record?.status || ExecutionState.PENDING)}
|
||||
iconOnly
|
||||
noBackground
|
||||
iconSize={20}
|
||||
/>
|
||||
<Text className={css.number}>{`#${record.number}.`}</Text>
|
||||
<Text className={css.desc}>{record.title}</Text>
|
||||
</Layout.Horizontal>
|
||||
@ -83,14 +88,13 @@ const ExecutionList = () => {
|
||||
<Avatar email={record.author_email} name={record.author_name} size="small" hoverCard={false} />
|
||||
{/* TODO need logic here for different trigger types */}
|
||||
<Text className={css.author}>{`${record.author_name} triggered manually`}</Text>
|
||||
<Text className={css.divider}>{`|`}</Text>
|
||||
{/* TODO Will need to replace this with commit action - wont match Yifan designs */}
|
||||
<PipeSeparator height={7} />
|
||||
{/* TODO Will need to replace this with commit component - wont match Yifan designs */}
|
||||
<a rel="noreferrer noopener" className={css.hash}>
|
||||
{record.after}
|
||||
</a>
|
||||
</Layout.Horizontal>
|
||||
</Layout.Vertical>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -158,7 +162,6 @@ const ExecutionList = () => {
|
||||
<Container margin={{ top: 'medium' }}>
|
||||
{!!executions?.length && (
|
||||
<Table<TypesExecution>
|
||||
className={css.table}
|
||||
columns={columns}
|
||||
data={executions || []}
|
||||
onRowClick={executionInfo =>
|
||||
@ -170,7 +173,6 @@ const ExecutionList = () => {
|
||||
})
|
||||
)
|
||||
}
|
||||
getRowClassName={row => cx(css.row, !row.original.number && css.noDesc)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@ -11,76 +11,49 @@
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.table {
|
||||
[class*='TableV2--header'] [class*='variation-table-headers'] {
|
||||
text-transform: none;
|
||||
color: var(--grey-400);
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.row {
|
||||
height: 80px;
|
||||
box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.08), 0px 0.5px 2px rgba(96, 97, 112, 0.16);
|
||||
overflow: hidden;
|
||||
|
||||
&.noDesc > div {
|
||||
height: 44px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nameContainer {
|
||||
position: relative;
|
||||
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
align-items: baseline !important;
|
||||
width: calc(100% - 100px) !important;
|
||||
|
||||
> span {
|
||||
width: 100%;
|
||||
> span {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
& + span:last-of-type {
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.pinned {
|
||||
transform: rotate(-90deg);
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: -43px;
|
||||
font-size: var(--font-size-xsmall) !important;
|
||||
padding: 6px 14px;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.repoName {
|
||||
font-weight: 600 !important;
|
||||
font-size: 16px !important;
|
||||
line-height: 24px !important;
|
||||
color: var(--grey-800);
|
||||
|
||||
.repoScope {
|
||||
color: var(--grey-400);
|
||||
padding: 2px 6px;
|
||||
font-size: var(--font-size-xsmall) !important;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--grey-200);
|
||||
display: inline-block;
|
||||
margin-left: var(--spacing-medium);
|
||||
text-transform: uppercase;
|
||||
line-height: 16px;
|
||||
}
|
||||
font-size: var(--font-size-normal) !important;
|
||||
color: var(--grey-700) !important;
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: var(--grey-500);
|
||||
font-size: var(--font-size-small);
|
||||
padding-top: var(--spacing-xsmall) !important;
|
||||
color: var(--grey-700) !important;
|
||||
font-size: var(--font-size-small) !important;
|
||||
font-style: normal !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin: 0 0 0 -3px !important;
|
||||
}
|
||||
|
||||
.author {
|
||||
color: var(--grey500) !important;
|
||||
font-size: var(--font-size-small) !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.hash {
|
||||
color: var(--primary-7) !important;
|
||||
font-family: Roboto Mono !important;
|
||||
font-size: var(--font-size-small) !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.triggerLayout {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.statusIcon {
|
||||
align-self: center !important;
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ declare const styles: {
|
||||
readonly main: string
|
||||
readonly layout: string
|
||||
readonly withError: string
|
||||
readonly table: string
|
||||
readonly row: string
|
||||
readonly noDesc: string
|
||||
readonly nameContainer: string
|
||||
readonly name: string
|
||||
readonly pinned: string
|
||||
readonly repoName: string
|
||||
readonly repoScope: string
|
||||
readonly desc: string
|
||||
readonly avatar: string
|
||||
readonly author: string
|
||||
readonly hash: string
|
||||
readonly triggerLayout: string
|
||||
readonly spacer: string
|
||||
readonly statusIcon: string
|
||||
}
|
||||
export default styles
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
ButtonVariation,
|
||||
Container,
|
||||
@ -7,7 +8,8 @@ import {
|
||||
Layout,
|
||||
PageBody,
|
||||
TableV2 as Table,
|
||||
Text
|
||||
Text,
|
||||
Utils
|
||||
} from '@harnessio/uicore'
|
||||
import { Color } from '@harnessio/design-system'
|
||||
import cx from 'classnames'
|
||||
@ -15,11 +17,12 @@ import type { CellProps, Column } from 'react-table'
|
||||
import Keywords from 'react-keywords'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useGet } from 'restful-react'
|
||||
import { Calendar, Timer, GitFork } from 'iconoir-react'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||
import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner'
|
||||
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
||||
import { LIST_FETCHING_LIMIT, PageBrowserProps, formatDate, getErrorMessage, voidFn } from 'utils/Utils'
|
||||
import { LIST_FETCHING_LIMIT, PageBrowserProps, getErrorMessage, timeDistance, voidFn } from 'utils/Utils'
|
||||
import type { TypesPipeline } from 'services/code'
|
||||
import { useQueryParams } from 'hooks/useQueryParams'
|
||||
import { usePageIndex } from 'hooks/usePageIndex'
|
||||
@ -27,6 +30,9 @@ import { ResourceListingPagination } from 'components/ResourceListingPagination/
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
||||
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
|
||||
import { ExecutionStatus, ExecutionState } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
import { getStatus } from 'utils/PipelineUtils'
|
||||
import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator'
|
||||
import noPipelineImage from '../RepositoriesListing/no-repo.svg'
|
||||
import css from './PipelineList.module.scss'
|
||||
|
||||
@ -48,8 +54,9 @@ const PipelineList = () => {
|
||||
response
|
||||
} = useGet<TypesPipeline[]>({
|
||||
path: `/api/v1/repos/${repoMetadata?.path}/+/pipelines`,
|
||||
queryParams: { page, limit: LIST_FETCHING_LIMIT, query: searchTerm },
|
||||
lazy: !repoMetadata
|
||||
queryParams: { page, limit: LIST_FETCHING_LIMIT, query: searchTerm, latest: true },
|
||||
lazy: !repoMetadata,
|
||||
debounce: 500
|
||||
})
|
||||
|
||||
const NewPipelineButton = (
|
||||
@ -66,33 +73,87 @@ const PipelineList = () => {
|
||||
() => [
|
||||
{
|
||||
Header: getString('pipelines.name'),
|
||||
width: 'calc(100% - 180px)',
|
||||
width: 'calc(50% - 90px)',
|
||||
Cell: ({ row }: CellProps<TypesPipeline>) => {
|
||||
const record = row.original
|
||||
return (
|
||||
<Container className={css.nameContainer}>
|
||||
<Layout.Horizontal spacing="small" style={{ flexGrow: 1 }}>
|
||||
<Layout.Vertical flex className={css.name}>
|
||||
<Layout.Horizontal spacing="small" className={css.nameContainer}>
|
||||
<ExecutionStatus
|
||||
status={getStatus(record?.execution?.status || ExecutionState.PENDING)}
|
||||
iconOnly
|
||||
noBackground
|
||||
iconSize={24}
|
||||
className={css.statusIcon}
|
||||
/>
|
||||
<Text className={css.repoName}>
|
||||
<Keywords value={searchTerm}>{record.uid}</Keywords>
|
||||
</Text>
|
||||
{record.description && <Text className={css.desc}>{record.description}</Text>}
|
||||
</Layout.Vertical>
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
Header: getString('repos.updated'),
|
||||
Header: getString('pipelines.lastExecution'),
|
||||
width: 'calc(50% - 90px)',
|
||||
Cell: ({ row }: CellProps<TypesPipeline>) => {
|
||||
const record = row.original.execution
|
||||
|
||||
return record ? (
|
||||
<Layout.Vertical spacing={'small'}>
|
||||
<Layout.Horizontal spacing={'small'} style={{ alignItems: 'center' }}>
|
||||
<Text className={css.desc}>{`#${record.number}`}</Text>
|
||||
<PipeSeparator height={7} />
|
||||
<Text className={css.desc}>{record.title}</Text>
|
||||
</Layout.Horizontal>
|
||||
<Layout.Horizontal spacing={'xsmall'} style={{ alignItems: 'center' }}>
|
||||
<Avatar
|
||||
email={record.author_email}
|
||||
name={record.author_name}
|
||||
size="small"
|
||||
hoverCard={false}
|
||||
className={css.avatar}
|
||||
/>
|
||||
{/* TODO need logic here for different trigger types */}
|
||||
<Text className={css.author}>{record.author_name}</Text>
|
||||
<PipeSeparator height={7} />
|
||||
<GitFork height={12} width={12} color={Utils.getRealCSSColor(Color.GREY_500)} />
|
||||
<Text className={css.author}>{record.source}</Text>
|
||||
<PipeSeparator height={7} />
|
||||
{/* TODO Will need to replace this with commit component - wont match Yifan designs */}
|
||||
<a rel="noreferrer noopener" className={css.hash}>
|
||||
{/* {record.after} */}
|
||||
hardcoded
|
||||
</a>
|
||||
</Layout.Horizontal>
|
||||
</Layout.Vertical>
|
||||
) : (
|
||||
<div className={css.spacer} />
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
Header: getString('pipelines.time'),
|
||||
width: '180px',
|
||||
Cell: ({ row }: CellProps<TypesPipeline>) => {
|
||||
return (
|
||||
<Layout.Horizontal style={{ alignItems: 'center' }}>
|
||||
<Text color={Color.BLACK} lineClamp={1} rightIconProps={{ size: 10 }} width={120}>
|
||||
{formatDate(row.original.updated as number)}
|
||||
const record = row.original.execution
|
||||
|
||||
return record ? (
|
||||
<Layout.Vertical spacing={'small'}>
|
||||
<Layout.Horizontal spacing={'small'} style={{ alignItems: 'center' }}>
|
||||
<Timer color={Utils.getRealCSSColor(Color.GREY_500)} />
|
||||
<Text inline color={Color.GREY_500} lineClamp={1} width={180} font={{ size: 'small' }}>
|
||||
{timeDistance(record.started, record.finished)}
|
||||
</Text>
|
||||
</Layout.Horizontal>
|
||||
<Layout.Horizontal spacing={'small'} style={{ alignItems: 'center' }}>
|
||||
<Calendar color={Utils.getRealCSSColor(Color.GREY_500)} />
|
||||
<Text inline color={Color.GREY_500} lineClamp={1} width={180} font={{ size: 'small' }}>
|
||||
{timeDistance(record.finished, Date.now())} ago
|
||||
</Text>
|
||||
</Layout.Horizontal>
|
||||
</Layout.Vertical>
|
||||
) : (
|
||||
<div className={css.spacer} />
|
||||
)
|
||||
},
|
||||
disableSortBy: true
|
||||
@ -133,7 +194,6 @@ const PipelineList = () => {
|
||||
<Container margin={{ top: 'medium' }}>
|
||||
{!!pipelines?.length && (
|
||||
<Table<TypesPipeline>
|
||||
className={css.table}
|
||||
columns={columns}
|
||||
data={pipelines || []}
|
||||
onRowClick={pipelineInfo =>
|
||||
@ -144,7 +204,6 @@ const PipelineList = () => {
|
||||
})
|
||||
)
|
||||
}
|
||||
getRowClassName={row => cx(css.row, !row.original.description && css.noDesc)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@ -27,7 +27,7 @@ import { useStrings } from 'framework/strings'
|
||||
import { MarkdownViewer } from 'components/MarkdownViewer/MarkdownViewer'
|
||||
import type { PRChecksDecisionResult } from 'hooks/usePRChecksDecision'
|
||||
import type { TypesCheck } from 'services/code'
|
||||
import { PRCheckExecutionState, PRCheckExecutionStatus } from 'components/PRCheckExecutionStatus/PRCheckExecutionStatus'
|
||||
import { ExecutionState, ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
import css from './Checks.module.scss'
|
||||
|
||||
interface ChecksProps extends Pick<GitInfoProps, 'repoMetadata' | 'pullRequestMetadata'> {
|
||||
@ -77,11 +77,11 @@ export const Checks: React.FC<ChecksProps> = props => {
|
||||
<Render when={selectedItemData}>
|
||||
<Container className={css.header}>
|
||||
<Layout.Horizontal className={css.headerLayout} spacing="small">
|
||||
<PRCheckExecutionStatus
|
||||
<ExecutionStatus
|
||||
className={cx(css.status, {
|
||||
[css.invert]: selectedItemData?.status === PRCheckExecutionState.PENDING
|
||||
[css.invert]: selectedItemData?.status === ExecutionState.PENDING
|
||||
})}
|
||||
status={selectedItemData?.status as PRCheckExecutionState}
|
||||
status={selectedItemData?.status as ExecutionState}
|
||||
iconSize={20}
|
||||
noBackground
|
||||
iconOnly
|
||||
@ -162,11 +162,11 @@ const ChecksMenu: React.FC<ChecksMenuProps> = ({
|
||||
} else {
|
||||
// Find and set a default selected item. Order: Error, Failure, Running, Success, Pending
|
||||
const defaultSelectedItem =
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === PRCheckExecutionState.ERROR) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === PRCheckExecutionState.FAILURE) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === PRCheckExecutionState.RUNNING) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === PRCheckExecutionState.SUCCESS) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === PRCheckExecutionState.PENDING) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === ExecutionState.ERROR) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === ExecutionState.FAILURE) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === ExecutionState.RUNNING) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === ExecutionState.SUCCESS) ||
|
||||
prChecksDecisionResult?.data?.find(({ status }) => status === ExecutionState.PENDING) ||
|
||||
prChecksDecisionResult?.data?.[0]
|
||||
|
||||
if (defaultSelectedItem) {
|
||||
@ -266,9 +266,9 @@ const CheckMenuItem: React.FC<CheckMenuItemProps> = ({ expandable, isSelected =
|
||||
{timeDistance(itemData.updated, itemData.created)}
|
||||
</Text>
|
||||
|
||||
<PRCheckExecutionStatus
|
||||
<ExecutionStatus
|
||||
className={cx(css.status, css.noShrink)}
|
||||
status={itemData.status as PRCheckExecutionState}
|
||||
status={itemData.status as ExecutionState}
|
||||
iconSize={16}
|
||||
noBackground
|
||||
iconOnly
|
||||
|
@ -5,7 +5,7 @@ import { FontVariation } from '@harnessio/design-system'
|
||||
import { Link } from 'react-router-dom'
|
||||
import type { GitInfoProps } from 'utils/GitUtils'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { PRCheckExecutionStatus, PRCheckExecutionState } from 'components/PRCheckExecutionStatus/PRCheckExecutionStatus'
|
||||
import { ExecutionStatus, ExecutionState } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
import { useShowRequestError } from 'hooks/useShowRequestError'
|
||||
import type { TypesCheck } from 'services/code'
|
||||
import { useAppContext } from 'AppContext'
|
||||
@ -50,7 +50,7 @@ export function ChecksOverview({ repoMetadata, pullRequestMetadata, prChecksDeci
|
||||
</Truthy>
|
||||
<Falsy>
|
||||
<Layout.Horizontal spacing="small" className={css.layout}>
|
||||
<PRCheckExecutionStatus status={overallStatus} noBackground iconOnly />
|
||||
<ExecutionStatus status={overallStatus} noBackground iconOnly />
|
||||
<Text font={{ variation: FontVariation.LEAD }}>{getString('pr.checks')}</Text>
|
||||
<Text color={color} padding={{ left: 'small' }} font={{ variation: FontVariation.FORM_MESSAGE_WARNING }}>
|
||||
{message}
|
||||
@ -94,7 +94,7 @@ const CheckSection: React.FC<CheckSectionProps> = ({ repoMetadata, pullRequestMe
|
||||
<Container className={css.row} key={uid}>
|
||||
<Layout.Horizontal className={css.rowLayout}>
|
||||
<Container className={css.status}>
|
||||
<PRCheckExecutionStatus status={status as PRCheckExecutionState} />
|
||||
<ExecutionStatus status={status as ExecutionState} />
|
||||
</Container>
|
||||
|
||||
<Link
|
||||
|
@ -15,7 +15,7 @@ import type { TypesPullReq, TypesPullReqStats, TypesRepository } from 'services/
|
||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||
import { TabTitleWithCount, tabContainerCSS } from 'components/TabTitleWithCount/TabTitleWithCount'
|
||||
import { usePRChecksDecision } from 'hooks/usePRChecksDecision'
|
||||
import { PRCheckExecutionStatus } from 'components/PRCheckExecutionStatus/PRCheckExecutionStatus'
|
||||
import { ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
import { PullRequestMetaLine } from './PullRequestMetaLine'
|
||||
import { Conversation } from './Conversation/Conversation'
|
||||
import { Checks } from './Checks/Checks'
|
||||
@ -248,7 +248,7 @@ export default function PullRequest() {
|
||||
prChecksDecisionResult?.overallStatus ? (
|
||||
<Container className={css.checksCount}>
|
||||
<Layout.Horizontal className={css.checksCountLayout}>
|
||||
<PRCheckExecutionStatus
|
||||
<ExecutionStatus
|
||||
status={prChecksDecisionResult?.overallStatus}
|
||||
noBackground
|
||||
iconOnly
|
||||
|
@ -634,12 +634,12 @@ export interface TypesPipeline {
|
||||
created?: number
|
||||
default_branch?: string
|
||||
description?: string
|
||||
execution?: TypesExecution
|
||||
id?: number
|
||||
repo_id?: number
|
||||
seq?: number
|
||||
uid?: string
|
||||
updated?: number
|
||||
version?: number
|
||||
}
|
||||
|
||||
export interface TypesPlugin {
|
||||
@ -2239,6 +2239,10 @@ export interface ListPipelinesQueryParams {
|
||||
* The maximum number of results to return.
|
||||
*/
|
||||
limit?: number
|
||||
/**
|
||||
* Whether to fetch latest build information for each pipeline.
|
||||
*/
|
||||
latest?: boolean
|
||||
}
|
||||
|
||||
export interface ListPipelinesPathParams {
|
||||
|
@ -1971,6 +1971,12 @@ paths:
|
||||
maximum: 100
|
||||
minimum: 1
|
||||
type: integer
|
||||
- description: Whether to fetch latest build information for each pipeline.
|
||||
in: query
|
||||
name: latest
|
||||
required: false
|
||||
schema:
|
||||
type: boolean
|
||||
- in: path
|
||||
name: repo_ref
|
||||
required: true
|
||||
@ -2010,7 +2016,7 @@ paths:
|
||||
$ref: '#/components/schemas/UsererrorError'
|
||||
description: Internal Server Error
|
||||
tags:
|
||||
- repos
|
||||
- pipeline
|
||||
post:
|
||||
operationId: createPipeline
|
||||
parameters:
|
||||
@ -7231,6 +7237,8 @@ components:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
execution:
|
||||
$ref: '#/components/schemas/TypesExecution'
|
||||
id:
|
||||
type: integer
|
||||
repo_id:
|
||||
@ -7241,8 +7249,6 @@ components:
|
||||
type: string
|
||||
updated:
|
||||
type: integer
|
||||
version:
|
||||
type: integer
|
||||
type: object
|
||||
TypesPlugin:
|
||||
properties:
|
||||
|
16
web/src/utils/PipelineUtils.ts
Normal file
16
web/src/utils/PipelineUtils.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { ExecutionState } from 'components/ExecutionStatus/ExecutionStatus'
|
||||
|
||||
export const getStatus = (status: string): ExecutionState => {
|
||||
switch (status) {
|
||||
case 'success':
|
||||
return ExecutionState.SUCCESS
|
||||
case 'failed':
|
||||
return ExecutionState.FAILURE
|
||||
case 'running':
|
||||
return ExecutionState.RUNNING
|
||||
case 'pending':
|
||||
return ExecutionState.PENDING
|
||||
default:
|
||||
return ExecutionState.PENDING
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user