Merge branch 'execution-list-WIP' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#380)

This commit is contained in:
Dan Wilson 2023-08-30 17:41:51 +00:00 committed by Harness
commit 1093153cad
12 changed files with 111 additions and 48 deletions

View File

@ -6,6 +6,7 @@ import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import type { CODEProps } from 'RouteDefinitions'
import type { TypesStage } from 'services/code'
import ConsoleStep from 'components/ConsoleStep/ConsoleStep'
import { timeDistance } from 'utils/Utils'
import css from './Console.module.scss'
interface ConsoleProps {
@ -23,10 +24,12 @@ const Console: FC<ConsoleProps> = ({ stage }) => {
<Text font={{ variation: FontVariation.H4 }} color={Color.WHITE} padding={{ left: 'large', right: 'large' }}>
{stage?.name}
</Text>
<Text font={{ variation: FontVariation.BODY }} color={Color.GREY_500}>
{/* this needs fixed */}
Success in 5 mins
</Text>
{stage?.started && stage?.stopped && (
<Text font={{ variation: FontVariation.BODY }} color={Color.GREY_500}>
{/* this needs fixed */}
{timeDistance(stage?.started, stage?.stopped)}
</Text>
)}
</Layout.Horizontal>
</Container>
<Layout.Vertical className={css.steps} spacing="small">

View File

@ -6,9 +6,11 @@
width: 1.5rem;
color: #999;
margin-right: 1rem;
font-family: 'Roboto Mono' !important;
}
.log {
color: white !important;
margin-bottom: 1rem;
font-family: 'Roboto Mono' !important;
}

View File

@ -3,3 +3,8 @@
align-items: center;
cursor: pointer;
}
.loading {
margin-left: 2.3rem !important;
margin-top: 1.5rem !important;
}

View File

@ -2,5 +2,6 @@
// this is an auto-generated file
declare const styles: {
readonly stepLayout: string
readonly loading: string
}
export default styles

View File

@ -6,6 +6,7 @@ import { Text } from '@harnessio/uicore'
import type { TypesStep } from 'services/code'
import { timeDistance } from 'utils/Utils'
import ConsoleLogs from 'components/ConsoleLogs/ConsoleLogs'
import { useStrings } from 'framework/strings'
import css from './ConsoleStep.module.scss'
interface ConsoleStepProps {
@ -17,6 +18,8 @@ interface ConsoleStepProps {
}
const ConsoleStep: FC<ConsoleStepProps> = ({ step, stageNumber, spaceName, pipelineName, executionNumber }) => {
const { getString } = useStrings()
const [isOpened, setIsOpened] = React.useState(false)
const { data, error, loading, refetch } = useGet<string>({
@ -50,7 +53,7 @@ const ConsoleStep: FC<ConsoleStepProps> = ({ step, stageNumber, spaceName, pipel
{isOpened ? (
loading ? (
<div>Loading...</div>
<div className={css.loading}>{getString('loading')}</div>
) : error ? (
<div>Error: {error}</div>
) : data ? (

View File

@ -169,9 +169,11 @@ export interface StringsMap {
enterUser: string
error: string
error404Text: string
'executions.description': string
'executions.name': string
'executions.newExecutionButton': string
'executions.noData': string
'executions.time': string
executor: string
existingAccount: string
expiration: string

View File

@ -626,8 +626,10 @@ pipelines:
name: Pipeline Name
executions:
noData: There are no executions :(
newExecutionButton: New Execution
newExecutionButton: Run Pipeline
name: Execution Name
description: Description
time: Time
selectRange: Shift-click to select a range
allCommits: All Commits
secrets:

View File

@ -29,17 +29,19 @@ const Execution = () => {
path: `/api/v1/pipelines/${space}/${pipeline}/+/executions/${executionNum}`
})
const [selectedStage, setSelectedStage] = useState<number | null>(null)
const [selectedStage, setSelectedStage] = useState<number | null>(1)
return (
<Container className={css.main}>
<PageHeader title={execution?.title} />
<PageHeader title={execution?.title}>
<div>hello</div>
</PageHeader>
<PageBody
className={cx({ [css.withError]: !!error })}
error={error ? getErrorMessage(error) : null}
retryOnError={voidFn(refetch)}
noData={{
when: () => !execution,
when: () => !execution && !loading,
image: noExecutionImage,
message: getString('executions.noData')
// button: NewExecutionButton

View File

@ -59,28 +59,37 @@
padding: 6px 14px;
}
.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;
}
.number {
color: var(--grey-400) !important;
font-size: 0.875rem !important;
font-weight: 500 !important;
}
.desc {
color: var(--grey-500);
font-size: var(--font-size-small);
padding-top: var(--spacing-xsmall) !important;
color: var(--grey-800) !important;
font-size: 0.875rem !important;
font-weight: 600 !important;
}
.author {
color: var(--grey500) !important;
font-size: 0.6875rem !important;
font-weight: 600 !important;
}
.hash {
color: var(--primary-7) !important;
font-family: Roboto Mono !important;
font-size: 0.75rem;
font-weight: 500;
}
.triggerLayout {
align-items: center !important;
}
.divider {
color: var(--grey-300) !important;
font-size: 0.25rem !important;
}
}

View File

@ -10,8 +10,11 @@ declare const styles: {
readonly nameContainer: string
readonly name: string
readonly pinned: string
readonly repoName: string
readonly repoScope: string
readonly number: string
readonly desc: string
readonly author: string
readonly hash: string
readonly triggerLayout: string
readonly divider: string
}
export default styles

View File

@ -1,5 +1,6 @@
import React, { useMemo } from 'react'
import {
Avatar,
Button,
ButtonVariation,
Container,
@ -8,18 +9,21 @@ import {
PageBody,
PageHeader,
TableV2 as Table,
Text
Text,
Utils
} from '@harnessio/uicore'
import { Color } from '@harnessio/design-system'
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'
import { useAppContext } from 'AppContext'
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 { CODEProps } from 'RouteDefinitions'
import type { TypesExecution } from 'services/code'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
@ -55,38 +59,60 @@ const ExecutionList = () => {
text={getString('executions.newExecutionButton')}
variation={ButtonVariation.PRIMARY}
disabled={true}
icon="plus"></Button>
icon="play-outline"></Button>
)
const columns: Column<TypesExecution>[] = useMemo(
() => [
{
Header: getString('executions.name'),
Header: getString('executions.description'),
width: 'calc(100% - 180px)',
Cell: ({ row }: CellProps<TypesExecution>) => {
const record = row.original
return (
<Container className={css.nameContainer}>
<Layout.Horizontal spacing="small" style={{ flexGrow: 1 }}>
<Layout.Vertical flex className={css.name}>
<Text className={css.repoName}>{record.number}</Text>
{record.status && <Text className={css.desc}>{record.status}</Text>}
</Layout.Vertical>
</Layout.Horizontal>
<Layout.Vertical>
<Layout.Horizontal spacing={'small'} style={{ alignItems: 'center' }}>
{/* TODO this icon need to depend on the status */}
<Icon name="success-tick" size={18} />
<Text className={css.number}>{`#${record.number}.`}</Text>
<Text className={css.desc}>{record.title}</Text>
</Layout.Horizontal>
<Layout.Horizontal spacing={'small'} style={{ alignItems: 'center', marginLeft: '1.2rem' }}>
<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 */}
<a rel="noreferrer noopener" className={css.hash}>
{record.after}
</a>
</Layout.Horizontal>
</Layout.Vertical>
</Container>
)
}
},
{
Header: getString('repos.updated'),
Header: getString('executions.time'),
width: '180px',
Cell: ({ row }: CellProps<TypesExecution>) => {
const record = row.original
return (
<Layout.Horizontal style={{ alignItems: 'center' }}>
<Text color={Color.BLACK} lineClamp={1} rightIconProps={{ size: 10 }} width={120}>
{formatDate(row.original.updated as number)}
</Text>
</Layout.Horizontal>
<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>
)
},
disableSortBy: true

View File

@ -111,12 +111,17 @@ export const timeDistance = (date1 = 0, date2 = 0) => {
return ''
}
const days = Math.floor(distance / (24 * 3600000)) // 24 hours * 60 minutes * 60 seconds * 1000 milliseconds
distance -= days * 24 * 3600000
const hours = Math.floor(distance / 3600000)
distance -= hours * 3600000
const minutes = Math.floor(distance / 60000)
distance -= minutes * 60000
const seconds = Math.floor(distance / 1000)
return `${hours ? hours + 'h ' : ''}${minutes ? minutes + 'm' : hours ? '0m' : ''} ${seconds}s`
return `${days ? days + 'd ' : ''}${hours ? hours + 'h ' : ''}${
minutes ? minutes + 'm' : hours || days ? '0m' : ''
} ${seconds}s`
}
const LOCALE = Intl.NumberFormat().resolvedOptions?.().locale || 'en-US'