feat: [AH-620]: support generic artifact details view (#3173)

* feat: [AH-620]: support generic artifact details view
This commit is contained in:
Shivanand Sonnad 2024-12-19 14:09:15 +00:00 committed by Harness
parent aaebea0c5d
commit 2ced78f102
11 changed files with 384 additions and 6 deletions

View File

@ -51,7 +51,7 @@
"@codemirror/view": "^6.9.6",
"@harnessio/design-system": "^2.1.1",
"@harnessio/icons": "^2.1.9",
"@harnessio/react-har-service-client": "^0.2.0",
"@harnessio/react-har-service-client": "^0.3.0",
"@harnessio/react-ssca-manager-client": "^0.65.0",
"@harnessio/uicore": "^4.1.2",
"@tanstack/react-query": "4.20.4",

View File

@ -25,6 +25,7 @@ import { String } from '@ar/frameworks/strings'
import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
import GenericVersionHeader from './GenericVersionHeader'
import GenericOverviewPage from './pages/overview/OverviewPage'
import GenericArtifactDetailsPage from './pages/artifact-details/GenericArtifactDetailsPage'
export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.GENERIC
@ -48,7 +49,7 @@ export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
case VersionDetailsTab.OVERVIEW:
return <GenericOverviewPage />
case VersionDetailsTab.ARTIFACT_DETAILS:
return <></>
return <GenericArtifactDetailsPage />
case VersionDetailsTab.DEPLOYMENTS:
return <></>
case VersionDetailsTab.OSS:

View File

@ -0,0 +1,80 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'
import { Page } from '@harnessio/uicore'
import { useGetArtifactFilesQuery } from '@harnessio/react-har-service-client'
import { DEFAULT_PAGE_INDEX } from '@ar/constants'
import type { VersionDetailsPathParams } from '@ar/routes/types'
import { useDecodedParams, useGetSpaceRef, useParentHooks } from '@ar/hooks'
import {
type ArtifactFileListPageQueryParams,
useArtifactFileListQueryParamOptions
} from '@ar/pages/version-details/components/ArtifactFileListTable/utils'
import ArtifactFileListTable from '@ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable'
import versionDetailsPageCss from '../../styles.module.scss'
export default function GenericArtifactDetailsPage() {
const registryRef = useGetSpaceRef()
const { useQueryParams, useUpdateQueryParams } = useParentHooks()
const { updateQueryParams } = useUpdateQueryParams<Partial<ArtifactFileListPageQueryParams>>()
const pathParams = useDecodedParams<VersionDetailsPathParams>()
const queryParamOptions = useArtifactFileListQueryParamOptions()
const queryParams = useQueryParams<ArtifactFileListPageQueryParams>(queryParamOptions)
const { searchTerm, page, size, sort } = queryParams
const [sortField, sortOrder] = sort || []
const {
isFetching: loading,
error,
data,
refetch
} = useGetArtifactFilesQuery({
registry_ref: registryRef,
artifact: pathParams.artifactIdentifier,
version: pathParams.versionIdentifier,
queryParams: {
searchTerm,
page,
size,
sortField,
sortOrder
}
})
const response = data?.content
return (
<Page.Body
className={versionDetailsPageCss.pageBody}
loading={loading}
error={error?.message || error}
retryOnError={() => refetch()}>
{response && (
<ArtifactFileListTable
data={response}
gotoPage={pageNumber => updateQueryParams({ page: pageNumber })}
setSortBy={sortArr => {
updateQueryParams({ sort: sortArr, page: DEFAULT_PAGE_INDEX })
}}
sortBy={sort}
/>
)}
</Page.Body>
)
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.table {
--typography-size: 12px;
--typography-weight: 400;
--line-height: 20px;
padding: var(--spacing-large);
[role='cell'],
[role='columnheader'] {
width: auto !important;
padding-right: var(--spacing-large);
}
div[class*='TableV2--cells'],
div[class*='TableV2--header'] {
display: grid !important;
width: 100%; /* Ensure the container doesn't exceed 100% width */
grid-template-columns: minmax(var(--har-table-name-column-min-width), 15rem) 80px 350px minmax(0, 1fr) 100px;
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2023 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable */
// This is an auto-generated file
export declare const table: string

View File

@ -0,0 +1,121 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'
import classNames from 'classnames'
import type { Column } from 'react-table'
import { type PaginationProps, TableV2 } from '@harnessio/uicore'
import type { FileDetail, FileDetailResponseResponse } from '@harnessio/react-har-service-client'
import { useParentHooks } from '@ar/hooks'
import { useStrings } from '@ar/frameworks/strings'
import {
FileChecksumListCell,
FileCreatedCell,
FileDownloadCommandCell,
FileNameCell,
FileSizeCell
} from './ArtifactListTableCells'
import css from './ArtifactFileListTable.module.scss'
export interface FileListSortBy {
sort: 'name' | 'size' | 'created'
}
interface ArtifactFileListTableProps {
data: FileDetailResponseResponse
gotoPage: (pageNumber: number) => void
onPageSizeChange?: PaginationProps['onPageSizeChange']
setSortBy: (sortBy: string[]) => void
sortBy: string[]
minimal?: boolean
className?: string
}
export default function ArtifactFileListTable(props: ArtifactFileListTableProps): JSX.Element {
const { data, gotoPage, onPageSizeChange, sortBy, setSortBy, className } = props
const { useDefaultPaginationProps } = useParentHooks()
const { getString } = useStrings()
const { files } = data
const paginationProps = useDefaultPaginationProps({
itemCount: 0,
pageSize: 100,
pageCount: 1,
pageIndex: 1,
gotoPage,
onPageSizeChange
})
const [currentSort, currentOrder] = sortBy
const columns: Column<FileDetail>[] = React.useMemo(() => {
const getServerSortProps = (id: string) => {
return {
enableServerSort: true,
isServerSorted: currentSort === id,
isServerSortedDesc: currentOrder === 'DESC',
getSortedColumn: ({ sort }: FileListSortBy) => {
setSortBy([sort, currentOrder === 'DESC' ? 'ASC' : 'DESC'])
}
}
}
return [
{
Header: getString('versionDetails.artifactFiles.table.columns.name'),
accessor: 'name',
Cell: FileNameCell,
serverSortProps: getServerSortProps('name'),
width: ''
},
{
Header: getString('versionDetails.artifactFiles.table.columns.size'),
accessor: 'size',
Cell: FileSizeCell,
serverSortProps: getServerSortProps('size')
},
{
Header: getString('versionDetails.artifactFiles.table.columns.checksum'),
accessor: 'checksums',
Cell: FileChecksumListCell,
disableSortBy: true
},
{
Header: getString('versionDetails.artifactFiles.table.columns.downloadCommand'),
accessor: 'downloadCommand',
Cell: FileDownloadCommandCell,
disableSortBy: true
},
{
Header: getString('versionDetails.artifactFiles.table.columns.created'),
accessor: 'createdAt',
Cell: FileCreatedCell,
serverSortProps: getServerSortProps('createdAt')
}
].filter(Boolean) as unknown as Column<FileDetail>[]
}, [currentOrder, currentSort, getString])
return (
<TableV2
className={classNames(css.table, className)}
columns={columns}
data={files as FileDetail[]}
pagination={paginationProps}
sortable
/>
)
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'
import { Layout } from '@harnessio/uicore'
import type { FileDetail } from '@harnessio/react-har-service-client'
import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance } from 'react-table'
import { killEvent } from '@ar/common/utils'
import { useStrings } from '@ar/frameworks/strings'
import TableCells from '@ar/components/TableCells/TableCells'
import CommandBlock from '@ar/components/CommandBlock/CommandBlock'
type CellTypeWithActions<D extends Record<string, any>, V = any> = TableInstance<D> & {
column: ColumnInstance<D>
row: Row<D>
cell: Cell<D, V>
value: CellValue<V>
}
type CellType = Renderer<CellTypeWithActions<FileDetail>>
export const FileNameCell: CellType = ({ value }) => {
return <TableCells.TextCell value={value} />
}
export const FileSizeCell: CellType = ({ value }) => {
return <TableCells.SizeCell value={value} />
}
export const FileChecksumListCell: CellType = ({ value }) => {
const { getString } = useStrings()
if (Array.isArray(value) && value.length) {
return (
<Layout.Vertical spacing="xsmall">
{value.map(each => (
<TableCells.TextCell key={each} value={each} />
))}
</Layout.Vertical>
)
}
return <TableCells.TextCell value={getString('na')} />
}
export const FileCreatedCell: CellType = ({ value }) => {
return <TableCells.LastModifiedCell value={value} />
}
export const FileDownloadCommandCell: CellType = ({ value }) => {
const { getString } = useStrings()
if (!value) return <TableCells.TextCell value={getString('na')} />
return <CommandBlock noWrap commandSnippet={value} allowCopy onCopy={killEvent} />
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useMemo } from 'react'
import { useParentHooks } from '@ar/hooks'
import { DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE, DEFAULT_PIPELINE_LIST_TABLE_SORT } from '@ar/constants'
import type { UseQueryParamsOptions } from '@ar/__mocks__/hooks'
export type ArtifactFileListPageQueryParams = {
page: number
size: number
sort: string[]
searchTerm?: string
}
export const useArtifactFileListQueryParamOptions = (): UseQueryParamsOptions<ArtifactFileListPageQueryParams> => {
const { useQueryParamsOptions } = useParentHooks()
const _options = useQueryParamsOptions(
{
page: DEFAULT_PAGE_INDEX,
size: DEFAULT_PAGE_SIZE,
sort: DEFAULT_PIPELINE_LIST_TABLE_SORT
},
{ ignoreEmptyString: false }
)
const options = useMemo(() => ({ ..._options, strictNullHandling: true }), [_options])
return options
}

View File

@ -73,3 +73,11 @@ deploymentsTable:
triggeredBy: Triggered At
infra: Infrastructure
instanceCount: Instance Count
artifactFiles:
table:
columns:
name: Name
size: Size
checksum: Checksum
downloadCommand: Download Command
created: Created

View File

@ -152,6 +152,11 @@ export interface StringsMap {
'versionDetails.artifactDetails.layers.size': string
'versionDetails.artifactDetails.tabs.layers': string
'versionDetails.artifactDetails.tabs.manifest': string
'versionDetails.artifactFiles.table.columns.checksum': string
'versionDetails.artifactFiles.table.columns.created': string
'versionDetails.artifactFiles.table.columns.downloadCommand': string
'versionDetails.artifactFiles.table.columns.name': string
'versionDetails.artifactFiles.table.columns.size': string
'versionDetails.cards.container.title': string
'versionDetails.cards.container.versionDigest': string
'versionDetails.cards.deploymentsCard.buildTitle': string

View File

@ -1945,10 +1945,10 @@
yargs "^17.6.2"
zod "^3.19.1"
"@harnessio/react-har-service-client@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.2.0.tgz#83f1f793c18e0e796ba7b1652801bfd676854963"
integrity sha512-W4GSiBTiI6DOCo9eqJPmxEf9I7PJA01AxAf9TrQ21fxFDuZbSk0c3YvZFz7INiHGUnNrB5QTLVgCVZRvelOkgw==
"@harnessio/react-har-service-client@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.3.0.tgz#b434034093c6619effe42720c7c078d18a9ecc50"
integrity sha512-+pFkxlUUM9CEkB60kx3SjppCdHdycfJhRN6t4p1R0M/n93dQLrdI0uHkoDZEeWb0o1Q0oQ21pkwTYktQr24E3g==
dependencies:
"@harnessio/oats-cli" "^3.0.0"