move pipelines inside repos

This commit is contained in:
Dan Wilson 2023-08-31 16:13:55 +01:00
parent d15aa03dfd
commit 9f20c3a1b9
12 changed files with 2655 additions and 973 deletions

View File

@ -45,7 +45,7 @@ export interface CODERoutes {
toCODESpaceAccessControl: (args: Required<Pick<CODEProps, 'space'>>) => string toCODESpaceAccessControl: (args: Required<Pick<CODEProps, 'space'>>) => string
toCODESpaceSettings: (args: Required<Pick<CODEProps, 'space'>>) => string toCODESpaceSettings: (args: Required<Pick<CODEProps, 'space'>>) => string
toCODEPipelines: (args: Required<Pick<CODEProps, 'space'>>) => string toCODEPipelines: (args: Required<Pick<CODEProps, 'repoPath'>>) => string
toCODEPipelinesNew: (args: Required<Pick<CODEProps, 'space'>>) => string toCODEPipelinesNew: (args: Required<Pick<CODEProps, 'space'>>) => string
toCODESecrets: (args: Required<Pick<CODEProps, 'space'>>) => string toCODESecrets: (args: Required<Pick<CODEProps, 'space'>>) => string
@ -74,8 +74,8 @@ export interface CODERoutes {
toCODEWebhookDetails: (args: Required<Pick<CODEProps, 'repoPath' | 'webhookId'>>) => string toCODEWebhookDetails: (args: Required<Pick<CODEProps, 'repoPath' | 'webhookId'>>) => string
toCODESettings: (args: Required<Pick<CODEProps, 'repoPath'>>) => string toCODESettings: (args: Required<Pick<CODEProps, 'repoPath'>>) => string
toCODEExecutions: (args: Required<Pick<CODEProps, 'space' | 'pipeline'>>) => string toCODEExecutions: (args: Required<Pick<CODEProps, 'repoPath' | 'pipeline'>>) => string
toCODEExecution: (args: Required<Pick<CODEProps, 'space' | 'pipeline' | 'execution'>>) => string toCODEExecution: (args: Required<Pick<CODEProps, 'repoPath' | 'pipeline' | 'execution'>>) => string
toCODESecret: (args: Required<Pick<CODEProps, 'space' | 'secret'>>) => string toCODESecret: (args: Required<Pick<CODEProps, 'space' | 'secret'>>) => string
} }
@ -96,7 +96,7 @@ export const routes: CODERoutes = {
toCODESpaceAccessControl: ({ space }) => `/access-control/${space}`, toCODESpaceAccessControl: ({ space }) => `/access-control/${space}`,
toCODESpaceSettings: ({ space }) => `/settings/${space}`, toCODESpaceSettings: ({ space }) => `/settings/${space}`,
toCODEPipelines: ({ space }) => `/pipelines/${space}`, toCODEPipelines: ({ repoPath }) => `/${repoPath}/pipelines`,
toCODEPipelinesNew: ({ space }) => `/pipelines/${space}/new`, toCODEPipelinesNew: ({ space }) => `/pipelines/${space}/new`,
toCODESecrets: ({ space }) => `/secrets/${space}`, toCODESecrets: ({ space }) => `/secrets/${space}`,
@ -130,8 +130,7 @@ export const routes: CODERoutes = {
toCODEWebhookNew: ({ repoPath }) => `/${repoPath}/webhooks/new`, toCODEWebhookNew: ({ repoPath }) => `/${repoPath}/webhooks/new`,
toCODEWebhookDetails: ({ repoPath, webhookId }) => `/${repoPath}/webhook/${webhookId}`, toCODEWebhookDetails: ({ repoPath, webhookId }) => `/${repoPath}/webhook/${webhookId}`,
toCODEExecutions: ({ space, pipeline }) => `/pipelines/${space}/pipeline/${pipeline}`, toCODEExecutions: ({ repoPath, pipeline }) => `/${repoPath}/pipelines/${pipeline}`,
toCODEExecution: ({ space, pipeline, execution }) => toCODEExecution: ({ repoPath, pipeline, execution }) => `/${repoPath}/pipelines/${pipeline}/execution/${execution}`,
`/pipelines/${space}/pipeline/${pipeline}/execution/${execution}`,
toCODESecret: ({ space, secret }) => `/secrets/${space}/secret/${secret}` toCODESecret: ({ space, secret }) => `/secrets/${space}/secret/${secret}`
} }

View File

@ -167,7 +167,7 @@ export const RouteDestinations: React.FC = React.memo(function RouteDestinations
{OPEN_SOURCE_PIPELINES && ( {OPEN_SOURCE_PIPELINES && (
<Route <Route
path={routes.toCODEExecution({ path={routes.toCODEExecution({
space: pathProps.space, repoPath,
pipeline: pathProps.pipeline, pipeline: pathProps.pipeline,
execution: pathProps.execution execution: pathProps.execution
})} })}
@ -179,7 +179,7 @@ export const RouteDestinations: React.FC = React.memo(function RouteDestinations
)} )}
{OPEN_SOURCE_PIPELINES && ( {OPEN_SOURCE_PIPELINES && (
<Route path={routes.toCODEExecutions({ space: pathProps.space, pipeline: pathProps.pipeline })} exact> <Route path={routes.toCODEExecutions({ repoPath, pipeline: pathProps.pipeline })} exact>
<LayoutWithSideNav title={getString('pageTitle.executions')}> <LayoutWithSideNav title={getString('pageTitle.executions')}>
<ExecutionList /> <ExecutionList />
</LayoutWithSideNav> </LayoutWithSideNav>
@ -195,7 +195,7 @@ export const RouteDestinations: React.FC = React.memo(function RouteDestinations
)} )}
{OPEN_SOURCE_PIPELINES && ( {OPEN_SOURCE_PIPELINES && (
<Route path={routes.toCODEPipelines({ space: pathProps.space })} exact> <Route path={routes.toCODEPipelines({ repoPath })} exact>
<LayoutWithSideNav title={getString('pageTitle.pipelines')}> <LayoutWithSideNav title={getString('pageTitle.pipelines')}>
<PipelineList /> <PipelineList />
</LayoutWithSideNav> </LayoutWithSideNav>

View File

@ -2,19 +2,20 @@ import React, { FC } from 'react'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { Container, Layout, Text } from '@harnessio/uicore' import { Container, Layout, Text } from '@harnessio/uicore'
import { Color, FontVariation } from '@harnessio/design-system' import { Color, FontVariation } from '@harnessio/design-system'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import type { CODEProps } from 'RouteDefinitions' import type { CODEProps } from 'RouteDefinitions'
import type { TypesStage } from 'services/code' import type { TypesStage } from 'services/code'
import ConsoleStep from 'components/ConsoleStep/ConsoleStep' import ConsoleStep from 'components/ConsoleStep/ConsoleStep'
import { timeDistance } from 'utils/Utils' import { timeDistance } from 'utils/Utils'
// import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import css from './Console.module.scss' import css from './Console.module.scss'
interface ConsoleProps { interface ConsoleProps {
stage: TypesStage | undefined stage: TypesStage | undefined
repoPath: string
} }
const Console: FC<ConsoleProps> = ({ stage }) => { const Console: FC<ConsoleProps> = ({ stage, repoPath }) => {
const space = useGetSpaceParam() // const { repoMetadata, error, loading, refetch } = useGetRepositoryMetadata()
const { pipeline, execution: executionNum } = useParams<CODEProps>() const { pipeline, execution: executionNum } = useParams<CODEProps>()
return ( return (
@ -39,7 +40,7 @@ const Console: FC<ConsoleProps> = ({ stage }) => {
step={step} step={step}
executionNumber={Number(executionNum)} executionNumber={Number(executionNum)}
pipelineName={pipeline} pipelineName={pipeline}
spaceName={space} repoPath={repoPath}
stageNumber={stage.number} stageNumber={stage.number}
/> />
))} ))}

View File

@ -12,18 +12,18 @@ import css from './ConsoleStep.module.scss'
interface ConsoleStepProps { interface ConsoleStepProps {
step: TypesStep | undefined step: TypesStep | undefined
stageNumber: number | undefined stageNumber: number | undefined
spaceName: string repoPath: string
pipelineName: string | undefined pipelineName: string | undefined
executionNumber: number executionNumber: number
} }
const ConsoleStep: FC<ConsoleStepProps> = ({ step, stageNumber, spaceName, pipelineName, executionNumber }) => { const ConsoleStep: FC<ConsoleStepProps> = ({ step, stageNumber, repoPath, pipelineName, executionNumber }) => {
const { getString } = useStrings() const { getString } = useStrings()
const [isOpened, setIsOpened] = React.useState(false) const [isOpened, setIsOpened] = React.useState(false)
const { data, error, loading, refetch } = useGet<string>({ const { data, error, loading, refetch } = useGet<string>({
path: `/api/v1/pipelines/${spaceName}/${pipelineName}/+/executions/${executionNumber}/logs/${String( path: `/api/v1/repos/${repoPath}/+/pipelines/${pipelineName}/executions/${executionNumber}/logs/${String(
stageNumber stageNumber
)}/${String(step?.number)}`, )}/${String(step?.number)}`,
lazy: true lazy: true

View File

@ -14,12 +14,15 @@
margin: 0.5rem 0 0.5rem 1rem !important; margin: 0.5rem 0 0.5rem 1rem !important;
cursor: pointer; cursor: pointer;
&:not(:last-child) {
border-bottom: 1px solid var(--grey-100);
}
.layout { .layout {
display: flex; display: flex;
align-items: center; align-items: center;
min-height: var(--stage-title-height); min-height: var(--stage-title-height);
padding: 0 var(--spacing-medium) 0 var(--spacing-medium); padding: 0 var(--spacing-medium) 0 var(--spacing-medium);
border-radius: 10px 0 0 10px !important;
&.selected { &.selected {
background-color: var(--primary-1); background-color: var(--primary-1);

View File

@ -18,7 +18,7 @@ interface ExecutionStageProps {
setSelectedStage: (selectedStage: number | null) => void setSelectedStage: (selectedStage: number | null) => void
} }
const ExecutionStage: FC<ExecutionStageProps> = ({ stage, isSelected = false, setSelectedStage = () => {} }) => { const ExecutionStage: FC<ExecutionStageProps> = ({ stage, isSelected = false, setSelectedStage }) => {
return ( return (
<Container <Container
className={css.menuItem} className={css.menuItem}

View File

@ -1,21 +1,19 @@
import React, { useMemo, useState } from 'react' import React, { useMemo, useState } from 'react'
import { Container, Layout } from '@harnessio/uicore' import { Container, Layout } from '@harnessio/uicore'
import { Render } from 'react-jsx-match' import { Render } from 'react-jsx-match'
import { useHistory, useRouteMatch, useParams } from 'react-router-dom' import { useHistory, useRouteMatch } from 'react-router-dom'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata' import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { useStrings } from 'framework/strings' import { useStrings } from 'framework/strings'
import type { TypesSpace } from 'services/code' import type { TypesSpace } from 'services/code'
import { SpaceSelector } from 'components/SpaceSelector/SpaceSelector' import { SpaceSelector } from 'components/SpaceSelector/SpaceSelector'
import { useAppContext } from 'AppContext' import { useAppContext } from 'AppContext'
import { useFeatureFlag } from 'hooks/useFeatureFlag' import { useFeatureFlag } from 'hooks/useFeatureFlag'
import type { CODEProps } from 'RouteDefinitions'
import { NavMenuItem } from './NavMenuItem' import { NavMenuItem } from './NavMenuItem'
import css from './DefaultMenu.module.scss' import css from './DefaultMenu.module.scss'
export const DefaultMenu: React.FC = () => { export const DefaultMenu: React.FC = () => {
const history = useHistory() const history = useHistory()
const { routes } = useAppContext() const { routes } = useAppContext()
const params = useParams<CODEProps>()
const [selectedSpace, setSelectedSpace] = useState<TypesSpace | undefined>() const [selectedSpace, setSelectedSpace] = useState<TypesSpace | undefined>()
const { repoMetadata, gitRef, commitRef } = useGetRepositoryMetadata() const { repoMetadata, gitRef, commitRef } = useGetRepositoryMetadata()
const { getString } = useStrings() const { getString } = useStrings()
@ -26,7 +24,6 @@ export const DefaultMenu: React.FC = () => {
[routeMatch] [routeMatch]
) )
const isCommitSelected = useMemo(() => routeMatch.path === '/:space*/:repoName/commit/:commitRef*', [routeMatch]) const isCommitSelected = useMemo(() => routeMatch.path === '/:space*/:repoName/commit/:commitRef*', [routeMatch])
const isPipelineSelected = routeMatch.path.startsWith('/pipelines/:space*/pipeline/:pipeline')
const { OPEN_SOURCE_PIPELINES, OPEN_SOURCE_SECRETS } = useFeatureFlag() const { OPEN_SOURCE_PIPELINES, OPEN_SOURCE_SECRETS } = useFeatureFlag()
return ( return (
@ -121,6 +118,17 @@ export const DefaultMenu: React.FC = () => {
})} })}
/> />
{OPEN_SOURCE_PIPELINES && (
<NavMenuItem
data-code-repo-section="pipelines"
isSubLink
label={getString('pageTitle.pipelines')}
to={routes.toCODEPipelines({
repoPath
})}
/>
)}
<NavMenuItem <NavMenuItem
data-code-repo-section="settings" data-code-repo-section="settings"
isSubLink isSubLink
@ -133,48 +141,6 @@ export const DefaultMenu: React.FC = () => {
</Container> </Container>
</Render> </Render>
{OPEN_SOURCE_PIPELINES && (
<Render when={selectedSpace}>
{/* icon is placeholder */}
<NavMenuItem
icon="pipeline"
label={getString('pageTitle.pipelines')}
to={routes.toCODEPipelines({ space: selectedSpace?.path as string })}
rightIcon={isPipelineSelected ? 'main-chevron-down' : 'main-chevron-right'}
textProps={{
rightIconProps: {
size: 10,
style: {
flexGrow: 1,
justifyContent: 'end',
display: 'flex'
}
}
}}
isDeselected={isPipelineSelected}
isHighlighted={isPipelineSelected}
/>
</Render>
)}
{OPEN_SOURCE_PIPELINES && (
<Render when={isPipelineSelected}>
<Container className={css.repoLinks}>
<Layout.Vertical spacing="small">
<NavMenuItem
isSubLink
isSelected={isPipelineSelected}
label={getString('pageTitle.executions')}
to={routes.toCODEExecutions({
space: selectedSpace?.path as string,
pipeline: params?.pipeline || ''
})}
/>
</Layout.Vertical>
</Container>
</Render>
)}
{OPEN_SOURCE_SECRETS && ( {OPEN_SOURCE_SECRETS && (
<Render when={selectedSpace}> <Render when={selectedSpace}>
{/* icon is placeholder */} {/* icon is placeholder */}

View File

@ -1,60 +1,80 @@
import { Container, PageHeader, PageBody } from '@harnessio/uicore' import { Container, PageBody } from '@harnessio/uicore'
import React, { useState } from 'react' import React, { useState } from 'react'
import cx from 'classnames' import cx from 'classnames'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { useGet } from 'restful-react' import { useGet } from 'restful-react'
import SplitPane from 'react-split-pane' import SplitPane from 'react-split-pane'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam' import { routes, type CODEProps } from 'RouteDefinitions'
import type { CODEProps } from 'RouteDefinitions'
import type { TypesExecution } from 'services/code' import type { TypesExecution } from 'services/code'
import ExecutionStageList from 'components/ExecutionStageList/ExecutionStageList' import ExecutionStageList from 'components/ExecutionStageList/ExecutionStageList'
import Console from 'components/Console/Console' import Console from 'components/Console/Console'
import { getErrorMessage, voidFn } from 'utils/Utils' import { getErrorMessage, voidFn } from 'utils/Utils'
import { useStrings } from 'framework/strings' import { useStrings } from 'framework/strings'
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner' import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
import noExecutionImage from '../RepositoriesListing/no-repo.svg' import noExecutionImage from '../RepositoriesListing/no-repo.svg'
import css from './Execution.module.scss' import css from './Execution.module.scss'
const Execution = () => { const Execution = () => {
const space = useGetSpaceParam()
const { pipeline, execution: executionNum } = useParams<CODEProps>() const { pipeline, execution: executionNum } = useParams<CODEProps>()
const { getString } = useStrings() const { getString } = useStrings()
const { repoMetadata, error, loading, refetch } = useGetRepositoryMetadata()
const { const {
data: execution, data: execution,
error, error: executionError,
loading, loading: executionLoading
refetch
} = useGet<TypesExecution>({ } = useGet<TypesExecution>({
path: `/api/v1/pipelines/${space}/${pipeline}/+/executions/${executionNum}` path: `/api/v1/repos/${repoMetadata?.path}/+/pipelines/${pipeline}/executions/${executionNum}`,
lazy: !repoMetadata
}) })
const [selectedStage, setSelectedStage] = useState<number | null>(1) const [selectedStage, setSelectedStage] = useState<number | null>(1)
return ( return (
<Container className={css.main}> <Container className={css.main}>
<PageHeader title={execution?.title}> <RepositoryPageHeader
<div>hello</div> repoMetadata={repoMetadata}
</PageHeader> title={execution?.title as string}
dataTooltipId="repositoryExecution"
extraBreadcrumbLinks={
repoMetadata && [
{
label: getString('pageTitle.pipelines'),
url: routes.toCODEPipelines({ repoPath: repoMetadata.path as string })
},
{
label: getString('pageTitle.executions'),
url: routes.toCODEExecutions({ repoPath: repoMetadata.path as string, pipeline: pipeline as string })
}
]
}
/>
<PageBody <PageBody
className={cx({ [css.withError]: !!error })} className={cx({ [css.withError]: !!error })}
error={error ? getErrorMessage(error) : null} error={error ? getErrorMessage(error || executionError) : null}
retryOnError={voidFn(refetch)} retryOnError={voidFn(refetch)}
noData={{ noData={{
when: () => !execution && !loading, when: () => !execution && !loading && !executionLoading,
image: noExecutionImage, image: noExecutionImage,
message: getString('executions.noData') message: getString('executions.noData')
// button: NewExecutionButton // button: NewExecutionButton
}}> }}>
<LoadingSpinner visible={loading} /> <LoadingSpinner visible={loading || executionLoading} withBorder={!!execution && executionLoading} />
<SplitPane split="vertical" size={300} minSize={200} maxSize={400}> {execution && (
<ExecutionStageList <SplitPane split="vertical" size={300} minSize={200} maxSize={400}>
stages={execution?.stages || []} <ExecutionStageList
setSelectedStage={setSelectedStage} stages={execution?.stages || []}
selectedStage={selectedStage} setSelectedStage={setSelectedStage}
/> selectedStage={selectedStage}
{selectedStage && <Console stage={execution?.stages?.[selectedStage - 1]} />} />
</SplitPane> {selectedStage && (
<Console stage={execution?.stages?.[selectedStage - 1]} repoPath={repoMetadata?.path as string} />
)}
</SplitPane>
)}
</PageBody> </PageBody>
</Container> </Container>
) )

View File

@ -7,7 +7,6 @@ import {
FlexExpander, FlexExpander,
Layout, Layout,
PageBody, PageBody,
PageHeader,
TableV2 as Table, TableV2 as Table,
Text, Text,
Utils Utils
@ -26,16 +25,16 @@ import { NoResultCard } from 'components/NoResultCard/NoResultCard'
import { LIST_FETCHING_LIMIT, PageBrowserProps, getErrorMessage, timeDistance, voidFn } from 'utils/Utils' import { LIST_FETCHING_LIMIT, PageBrowserProps, getErrorMessage, timeDistance, voidFn } from 'utils/Utils'
import type { CODEProps } from 'RouteDefinitions' import type { CODEProps } from 'RouteDefinitions'
import type { TypesExecution } from 'services/code' import type { TypesExecution } from 'services/code'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useQueryParams } from 'hooks/useQueryParams' import { useQueryParams } from 'hooks/useQueryParams'
import { usePageIndex } from 'hooks/usePageIndex' import { usePageIndex } from 'hooks/usePageIndex'
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination' import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
import noExecutionImage from '../RepositoriesListing/no-repo.svg' import noExecutionImage from '../RepositoriesListing/no-repo.svg'
import css from './ExecutionList.module.scss' import css from './ExecutionList.module.scss'
const ExecutionList = () => { const ExecutionList = () => {
const { routes } = useAppContext() const { routes } = useAppContext()
const space = useGetSpaceParam()
const { pipeline } = useParams<CODEProps>() const { pipeline } = useParams<CODEProps>()
const history = useHistory() const history = useHistory()
const { getString } = useStrings() const { getString } = useStrings()
@ -43,15 +42,17 @@ const ExecutionList = () => {
const pageInit = pageBrowser.page ? parseInt(pageBrowser.page) : 1 const pageInit = pageBrowser.page ? parseInt(pageBrowser.page) : 1
const [page, setPage] = usePageIndex(pageInit) const [page, setPage] = usePageIndex(pageInit)
const { repoMetadata, error, loading, refetch } = useGetRepositoryMetadata()
const { const {
data: executions, data: executions,
error, error: executionsError,
loading, loading: executionsLoading,
refetch,
response response
} = useGet<TypesExecution[]>({ } = useGet<TypesExecution[]>({
path: `/api/v1/pipelines/${space}/${pipeline}/+/executions`, path: `/api/v1/repos/${repoMetadata?.path}/+/pipelines/${pipeline}/executions`,
queryParams: { page, limit: LIST_FETCHING_LIMIT } queryParams: { page, limit: LIST_FETCHING_LIMIT },
lazy: !repoMetadata
}) })
const NewExecutionButton = ( const NewExecutionButton = (
@ -123,10 +124,23 @@ const ExecutionList = () => {
return ( return (
<Container className={css.main}> <Container className={css.main}>
<PageHeader title={getString('pageTitle.executions')} /> {/* <PageHeader title={getString('pageTitle.executions')} /> */}
<RepositoryPageHeader
repoMetadata={repoMetadata}
title={getString('pageTitle.executions')}
dataTooltipId="repositoryExecutions"
extraBreadcrumbLinks={
repoMetadata && [
{
label: getString('pageTitle.pipelines'),
url: routes.toCODEPipelines({ repoPath: repoMetadata.path as string })
}
]
}
/>
<PageBody <PageBody
className={cx({ [css.withError]: !!error })} className={cx({ [css.withError]: !!error })}
error={error ? getErrorMessage(error) : null} error={error ? getErrorMessage(error || executionsError) : null}
retryOnError={voidFn(refetch)} retryOnError={voidFn(refetch)}
noData={{ noData={{
when: () => executions?.length === 0, when: () => executions?.length === 0,
@ -134,7 +148,7 @@ const ExecutionList = () => {
message: getString('executions.noData'), message: getString('executions.noData'),
button: NewExecutionButton button: NewExecutionButton
}}> }}>
<LoadingSpinner visible={loading} /> <LoadingSpinner visible={loading || executionsLoading} withBorder={!!executions && executionsLoading} />
<Container padding="xlarge"> <Container padding="xlarge">
<Layout.Horizontal spacing="large" className={css.layout}> <Layout.Horizontal spacing="large" className={css.layout}>
@ -151,7 +165,7 @@ const ExecutionList = () => {
onRowClick={executionInfo => onRowClick={executionInfo =>
history.push( history.push(
routes.toCODEExecution({ routes.toCODEExecution({
space, repoPath: repoMetadata?.path as string,
pipeline: pipeline as string, pipeline: pipeline as string,
execution: String(executionInfo.number) execution: String(executionInfo.number)
}) })

View File

@ -6,7 +6,6 @@ import {
FlexExpander, FlexExpander,
Layout, Layout,
PageBody, PageBody,
PageHeader,
TableV2 as Table, TableV2 as Table,
Text Text
} from '@harnessio/uicore' } from '@harnessio/uicore'
@ -21,18 +20,18 @@ import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner' import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner'
import { NoResultCard } from 'components/NoResultCard/NoResultCard' import { NoResultCard } from 'components/NoResultCard/NoResultCard'
import { LIST_FETCHING_LIMIT, PageBrowserProps, formatDate, getErrorMessage, voidFn } from 'utils/Utils' import { LIST_FETCHING_LIMIT, PageBrowserProps, formatDate, getErrorMessage, voidFn } from 'utils/Utils'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import type { TypesPipeline } from 'services/code' import type { TypesPipeline } from 'services/code'
import { useQueryParams } from 'hooks/useQueryParams' import { useQueryParams } from 'hooks/useQueryParams'
import { usePageIndex } from 'hooks/usePageIndex' import { usePageIndex } from 'hooks/usePageIndex'
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination' import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
import { useAppContext } from 'AppContext' import { useAppContext } from 'AppContext'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
import noPipelineImage from '../RepositoriesListing/no-repo.svg' import noPipelineImage from '../RepositoriesListing/no-repo.svg'
import css from './PipelineList.module.scss' import css from './PipelineList.module.scss'
const PipelineList = () => { const PipelineList = () => {
const { routes } = useAppContext() const { routes } = useAppContext()
const space = useGetSpaceParam()
const history = useHistory() const history = useHistory()
const { getString } = useStrings() const { getString } = useStrings()
const [searchTerm, setSearchTerm] = useState<string | undefined>() const [searchTerm, setSearchTerm] = useState<string | undefined>()
@ -40,15 +39,17 @@ const PipelineList = () => {
const pageInit = pageBrowser.page ? parseInt(pageBrowser.page) : 1 const pageInit = pageBrowser.page ? parseInt(pageBrowser.page) : 1
const [page, setPage] = usePageIndex(pageInit) const [page, setPage] = usePageIndex(pageInit)
const { repoMetadata, error, loading, refetch } = useGetRepositoryMetadata()
const { const {
data: pipelines, data: pipelines,
error, error: pipelinesError,
loading, loading: pipelinesLoading,
refetch,
response response
} = useGet<TypesPipeline[]>({ } = useGet<TypesPipeline[]>({
path: `/api/v1/spaces/${space}/+/pipelines`, path: `/api/v1/repos/${repoMetadata?.path}/+/pipelines`,
queryParams: { page, limit: LIST_FETCHING_LIMIT, query: searchTerm } queryParams: { page, limit: LIST_FETCHING_LIMIT, query: searchTerm },
lazy: !repoMetadata
}) })
const NewPipelineButton = ( const NewPipelineButton = (
@ -102,10 +103,14 @@ const PipelineList = () => {
return ( return (
<Container className={css.main}> <Container className={css.main}>
<PageHeader title={getString('pageTitle.pipelines')} /> <RepositoryPageHeader
repoMetadata={repoMetadata}
title={getString('pageTitle.pipelines')}
dataTooltipId="repositoryPipelines"
/>
<PageBody <PageBody
className={cx({ [css.withError]: !!error })} className={cx({ [css.withError]: !!error })}
error={error ? getErrorMessage(error) : null} error={error ? getErrorMessage(error || pipelinesError) : null}
retryOnError={voidFn(refetch)} retryOnError={voidFn(refetch)}
noData={{ noData={{
when: () => pipelines?.length === 0 && searchTerm === undefined, when: () => pipelines?.length === 0 && searchTerm === undefined,
@ -113,7 +118,10 @@ const PipelineList = () => {
message: getString('pipelines.noData'), message: getString('pipelines.noData'),
button: NewPipelineButton button: NewPipelineButton
}}> }}>
<LoadingSpinner visible={loading && !searchTerm} /> <LoadingSpinner
visible={(loading || pipelinesLoading) && !searchTerm}
withBorder={!!pipelines && pipelinesLoading}
/>
<Container padding="xlarge"> <Container padding="xlarge">
<Layout.Horizontal spacing="large" className={css.layout}> <Layout.Horizontal spacing="large" className={css.layout}>
@ -129,7 +137,12 @@ const PipelineList = () => {
columns={columns} columns={columns}
data={pipelines || []} data={pipelines || []}
onRowClick={pipelineInfo => onRowClick={pipelineInfo =>
history.push(routes.toCODEExecutions({ space, pipeline: pipelineInfo.uid as string })) history.push(
routes.toCODEExecutions({
repoPath: repoMetadata?.path as string,
pipeline: pipelineInfo.uid as string
})
)
} }
getRowClassName={row => cx(css.row, !row.original.description && css.noDesc)} getRowClassName={row => cx(css.row, !row.original.description && css.noDesc)}
/> />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff