Skip to content

Commit

Permalink
feat: Show pull requests lists on clusters and services details pages (
Browse files Browse the repository at this point in the history
  • Loading branch information
maciaszczykm committed Aug 19, 2024
1 parent 4184e54 commit 78e2a73
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 21 deletions.
3 changes: 3 additions & 0 deletions assets/src/components/cd/cluster/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
CLUSTER_NODES_PATH,
CLUSTER_PARAM_ID,
CLUSTER_PODS_PATH,
CLUSTER_PRS_REL_PATH,
CLUSTER_SERVICES_PATH,
} from 'routes/cdRoutesConsts'
import { useTheme } from 'styled-components'
Expand All @@ -46,6 +47,7 @@ const directory = [
{ path: CLUSTER_METADATA_PATH, label: 'Metadata' },
{ path: CLUSTER_LOGS_PATH, label: 'Logs', logs: true },
{ path: CLUSTER_ADDONS_REL_PATH, label: 'Add-ons' },
{ path: CLUSTER_PRS_REL_PATH, label: 'PRs' },
] as const

const POLL_INTERVAL = 10 * 1000
Expand Down Expand Up @@ -130,6 +132,7 @@ export default function Cluster() {
scrollable={
tab !== 'services' &&
tab !== 'pods' &&
tab !== CLUSTER_PRS_REL_PATH &&
tab !== 'addons' &&
tab !== 'logs'
}
Expand Down
108 changes: 108 additions & 0 deletions assets/src/components/cd/cluster/ClusterPRs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { useTheme } from 'styled-components'
import { Input, LoopingLogo, SearchIcon, Table } from '@pluralsh/design-system'
import { ComponentProps, useState } from 'react'

import { FullHeightTableWrap } from '../../utils/layout/FullHeightTableWrap'
import {
ColActions,
ColCreator,
ColInsertedAt,
ColLabels,
ColService,
ColStatus,
ColTitle,
} from '../../pr/queue/PrQueueColumns'
import {
PRS_REACT_VIRTUAL_OPTIONS,
PR_QUERY_PAGE_SIZE,
} from '../../pr/queue/PrQueue'
import { GqlError } from '../../utils/Alert'
import { useFetchPaginatedData } from '../utils/useFetchPaginatedData'
import { usePullRequestsQuery } from '../../../generated/graphql'
import { useThrottle } from '../../hooks/useThrottle'

import { useClusterContext } from './Cluster'

export const columns = [
ColTitle,
ColStatus,
ColService,
ColCreator,
ColLabels,
ColInsertedAt,
ColActions,
]

export default function ClusterPRs() {
const { cluster } = useClusterContext()
const theme = useTheme()
const [searchString, setSearchString] = useState('')
const debouncedSearchString = useThrottle(searchString, 200)

const {
data,
loading,
error,
refetch,
pageInfo,
fetchNextPage,
setVirtualSlice,
} = useFetchPaginatedData(
{
queryHook: usePullRequestsQuery,
pageSize: PR_QUERY_PAGE_SIZE,
keyPath: ['pullRequests'],
},
{
q: debouncedSearchString,
clusterId: cluster.id,
}
)

const reactTableOptions: ComponentProps<typeof Table>['reactTableOptions'] = {
meta: { refetch },
}

if (error) return <GqlError error={error} />

if (!data) return <LoopingLogo />

return (
<div
css={{
display: 'flex',
flexDirection: 'column',
gap: theme.spacing.small,
height: '100%',
}}
>
<div css={{ display: 'flex', minWidth: 0, gap: theme.spacing.medium }}>
<Input
placeholder="Search"
startIcon={<SearchIcon />}
showClearButton
value={searchString}
onChange={(e) => setSearchString(e.currentTarget.value)}
css={{ flexGrow: 1 }}
/>
</div>
<FullHeightTableWrap>
<Table
columns={columns}
reactVirtualOptions={PRS_REACT_VIRTUAL_OPTIONS}
data={data?.pullRequests?.edges || []}
virtualizeRows
reactTableOptions={reactTableOptions}
hasNextPage={pageInfo?.hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={loading}
onVirtualSliceChange={setVirtualSlice}
css={{
maxHeight: 'unset',
height: '100%',
}}
/>
</FullHeightTableWrap>
</div>
)
}
5 changes: 4 additions & 1 deletion assets/src/components/cd/services/service/ServiceDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ import {
} from 'components/contexts/DocPageContext'
import { getDocsData } from 'components/apps/app/App'
import {
SERVICE_COMPONENTS_PATH,
SERVICE_PARAM_CLUSTER_ID,
SERVICE_PARAM_ID,
SERVICE_PRS_PATH,
getClusterDetailsPath,
getServiceDetailsPath,
} from 'routes/cdRoutesConsts'
Expand Down Expand Up @@ -123,7 +125,7 @@ export const getDirectory = ({

return [
{
path: 'components',
path: SERVICE_COMPONENTS_PATH,
label: (
<FractionalChip
label="Components"
Expand All @@ -143,6 +145,7 @@ export const getDirectory = ({
{ path: 'helm', label: 'Helm values', enabled: isAdmin },
{ path: 'dryrun', label: 'Dry run', enabled: !!dryRun },
{ path: 'revisions', label: 'Revisions', enabled: true },
{ path: SERVICE_PRS_PATH, label: 'Pull requests', enabled: true },
{
path: 'docs',
label: name ? `${capitalize(name)} docs` : 'Docs',
Expand Down
161 changes: 161 additions & 0 deletions assets/src/components/cd/services/service/ServicePRs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {
EmptyState,
Input,
LoopingLogo,
SearchIcon,
Table,
useSetBreadcrumbs,
} from '@pluralsh/design-system'
import { ComponentProps, useMemo, useState } from 'react'
import { useParams } from 'react-router-dom'
import isEmpty from 'lodash/isEmpty'
import {
CD_REL_PATH,
SERVICE_PARAM_CLUSTER_ID,
SERVICE_PARAM_ID,
SERVICE_PRS_PATH,
} from 'routes/cdRoutesConsts'
import { usePullRequestsQuery } from 'generated/graphql'
import { FullHeightTableWrap } from 'components/utils/layout/FullHeightTableWrap'
import { ScrollablePage } from 'components/utils/layout/ScrollablePage'
import { useTheme } from 'styled-components'

import {
ColActions,
ColCreator,
ColInsertedAt,
ColLabels,
ColStatus,
ColTitle,
} from '../../../pr/queue/PrQueueColumns'
import {
PRS_REACT_VIRTUAL_OPTIONS,
PR_QUERY_PAGE_SIZE,
} from '../../../pr/queue/PrQueue'
import { GqlError } from '../../../utils/Alert'
import { useThrottle } from '../../../hooks/useThrottle'
import { useFetchPaginatedData } from '../../utils/useFetchPaginatedData'

import {
getServiceDetailsBreadcrumbs,
useServiceContext,
} from './ServiceDetails'

export const columns = [
ColTitle,
ColStatus,
ColCreator,
ColLabels,
ColInsertedAt,
ColActions,
]

export default function ServicePRs() {
const theme = useTheme()
const { serviceId, clusterId } = useParams<{
[SERVICE_PARAM_ID]: string
[SERVICE_PARAM_CLUSTER_ID]: string
}>()
const { service } = useServiceContext()

useSetBreadcrumbs(
useMemo(
() => [
...getServiceDetailsBreadcrumbs({
cluster: service?.cluster || { id: clusterId || '' },
service: service || { id: serviceId || '' },
}),
{
label: 'pull requests',
url: `${CD_REL_PATH}/services/${serviceId}/${SERVICE_PRS_PATH}`,
},
],
[clusterId, service, serviceId]
)
)

const [searchString, setSearchString] = useState('')
const debouncedSearchString = useThrottle(searchString, 200)

const {
data,
loading,
error,
refetch,
pageInfo,
fetchNextPage,
setVirtualSlice,
} = useFetchPaginatedData(
{
queryHook: usePullRequestsQuery,
pageSize: PR_QUERY_PAGE_SIZE,
keyPath: ['pullRequests'],
},
{
q: debouncedSearchString,
serviceId,
}
)

const reactTableOptions: ComponentProps<typeof Table>['reactTableOptions'] = {
meta: { refetch },
}

if (error) return <GqlError error={error} />

if (!data) return <LoopingLogo />

return (
<ScrollablePage
scrollable={false}
heading="Pull requests"
>
<div
css={{
display: 'flex',
flexDirection: 'column',
rowGap: theme.spacing.medium,
height: '100%',
}}
>
<div
css={{
display: 'flex',
columnGap: theme.spacing.medium,
flexShrink: 0,
}}
>
<Input
placeholder="Search"
startIcon={<SearchIcon />}
showClearButton
value={searchString}
onChange={(e) => setSearchString(e.currentTarget.value)}
css={{ flexGrow: 1 }}
/>
</div>
{isEmpty(data?.pullRequests?.edges) ? (
<EmptyState message="No pull requests found" />
) : (
<FullHeightTableWrap>
<Table
columns={columns}
reactVirtualOptions={PRS_REACT_VIRTUAL_OPTIONS}
data={data?.pullRequests?.edges || []}
virtualizeRows
reactTableOptions={reactTableOptions}
hasNextPage={pageInfo?.hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={loading}
onVirtualSliceChange={setVirtualSlice}
css={{
maxHeight: 'unset',
height: '100%',
}}
/>
</FullHeightTableWrap>
)}
</div>
</ScrollablePage>
)
}
Loading

0 comments on commit 78e2a73

Please sign in to comment.