feat: [AH-1193]: new ui for global artifact list page (#3653)

* feat: [AH-1193]: remove size column from global artifact list page
* feat: [AH-1193]: Support artifact actions
* feat: [AH-1193]: support actions in global artifact list table
* feat: [AH-1193]: fix failing UTs
* feat: [AH-1193]: Update global artifact list view
This commit is contained in:
Shivanand Sonnad 2025-04-10 10:15:19 +00:00 committed by Harness
parent 414ecae70b
commit 2fdb6d6655
36 changed files with 654 additions and 94 deletions

View File

@ -49,7 +49,7 @@ export default function ActionButton({ children, isOpen, setOpen }: PropsWithChi
}}
onClick={e => {
e.stopPropagation()
setOpen(true)
setOpen(!isOpen)
}}
/>
)

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 React from 'react'
import copy from 'clipboard-copy'
import { useToaster } from '@harnessio/uicore'
import { useParentComponents } from '@ar/hooks'
import { useStrings } from '@ar/frameworks/strings'
interface CopyMenuItemProps {
value: string
onCopy?: () => void
}
function CopyMenuItem(props: CopyMenuItemProps): JSX.Element {
const { value, onCopy } = props
const { RbacMenuItem } = useParentComponents()
const { getString } = useStrings()
const { showSuccess } = useToaster()
const handleCopy = () => {
copy(value)
onCopy?.()
showSuccess(getString('copied'))
}
return <RbacMenuItem icon="code-copy" text={getString('actions.copyCommand')} onClick={handleCopy} />
}
export default CopyMenuItem

View File

@ -0,0 +1,29 @@
/*
* 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 { Link, LinkProps } from 'react-router-dom'
import { useParentComponents } from '@ar/hooks'
import css from './MenuItemTypes.module.scss'
function LinkMenuItem(props: LinkProps): JSX.Element {
const { RbacMenuItem } = useParentComponents()
return <RbacMenuItem text={<Link {...props} className={css.link} />} icon="main-view" />
}
export default LinkMenuItem

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
.link {
text-decoration: none;
color: inherit;
cursor: pointer;
display: block;
&:hover {
color: inherit;
text-decoration: none;
}
}

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 link: string

View File

@ -20,6 +20,7 @@ export const DEFAULT_PAGE_INDEX = 0
export const DEFAULT_PAGE_SIZE = 50
export const PAGE_SIZE_OPTIONS = [10, 20, 50, 100]
export const DEFAULT_PIPELINE_LIST_TABLE_SORT = ['updatedAt', 'DESC']
export const DEFAULT_ARTIFACT_LIST_TABLE_SORT = ['updatedAt', 'DESC']
export const DEFAULT_UPSTREAM_PROXY_LIST_TABLE_SORT = ['updatedAt', 'DESC']
export const DEFAULT_DATE_FORMAT = 'MMM DD, YYYY'

View File

@ -0,0 +1,40 @@
/*
* 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 { Text } from '@harnessio/uicore'
import { useStrings } from '@ar/frameworks/strings'
import type { RepositoryPackageType } from '@ar/common/types'
import versionFactory from './VersionFactory'
import type { ArtifactRowSubComponentProps } from './Version'
import type { VersionAbstractFactory } from './VersionAbstractFactory'
interface ArtifactRowSubComponentWidgetProps extends ArtifactRowSubComponentProps {
factory?: VersionAbstractFactory
packageType: RepositoryPackageType
}
export default function ArtifactRowSubComponentWidget(props: ArtifactRowSubComponentWidgetProps): JSX.Element {
const { factory = versionFactory, packageType, ...rest } = props
const { getString } = useStrings()
const repositoryType = factory?.getVersionType(packageType)
if (!repositoryType) {
return <Text intent="warning">{getString('stepNotFound')}</Text>
}
return repositoryType.renderArtifactRowSubComponent({ ...rest })
}

View File

@ -16,6 +16,7 @@
import type { PaginationProps } from '@harnessio/uicore'
import type {
ArtifactMetadata,
ArtifactSummary,
ArtifactVersionMetadata,
ArtifactVersionSummary,
@ -64,9 +65,14 @@ export interface VersionActionProps {
onClose?: () => void
}
export interface ArtifactRowSubComponentProps {
data: ArtifactMetadata
}
export abstract class VersionStep<T> {
protected abstract packageType: RepositoryPackageType
protected abstract allowedVersionDetailsTabs: VersionDetailsTab[]
protected abstract hasArtifactRowSubComponent: boolean
getPackageType(): string {
return this.packageType
@ -76,6 +82,10 @@ export abstract class VersionStep<T> {
return this.allowedVersionDetailsTabs
}
getHasArtifactRowSubComponent(): boolean {
return this.hasArtifactRowSubComponent
}
abstract renderVersionListTable(props: VersionListTableProps): JSX.Element
abstract renderVersionDetailsHeader(props: VersionDetailsHeaderProps<T>): JSX.Element
@ -85,4 +95,6 @@ export abstract class VersionStep<T> {
abstract renderArtifactActions(props: ArtifactActionProps): JSX.Element
abstract renderVersionActions(props: VersionActionProps): JSX.Element
abstract renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element
}

View File

@ -69,7 +69,7 @@ function ArtifactListPage(): JSX.Element {
const {
data,
refetch,
isLoading: loading,
isFetching: loading,
error
} = useGetAllHarnessArtifactsQuery({
space_ref: spaceRef,

View File

@ -59,7 +59,7 @@ function RegistryArtifactListPage({ pageBodyClassName }: RegistryArtifactListPag
const {
data,
refetch,
isLoading: loading,
isFetching: loading,
error
} = useGetAllArtifactsByRegistryQuery({
registry_ref: registryRef,

View File

@ -155,10 +155,9 @@ describe('Test Artifact List Page', () => {
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
})
const packageTypeSelect = getByTestId('package-type-select')
await userEvent.click(packageTypeSelect)
const packageTypeOption = getByText('repositoryTypes.docker')
await userEvent.click(packageTypeOption)
const packageTypeSelector = getByTestId('package-type-select')
expect(packageTypeSelector).toBeInTheDocument()
await testMultiSelectChange(packageTypeSelector, 'repositoryTypes.docker')
expect(useGetAllHarnessArtifactsQuery).toHaveBeenLastCalledWith({
space_ref: 'undefined/+',

View File

@ -34,7 +34,7 @@
div[class*='TableV2--cells'],
div[class*='TableV2--header'] {
display: grid !important;
grid-template-columns: minmax(var(--har-table-name-column-min-width), 1fr) 12rem 10rem 8rem 12rem 12rem 8rem;
grid-template-columns: 50px minmax(var(--har-table-name-column-min-width), 1fr) 12rem 10rem 10rem 14rem 8rem 40px;
}
}
@ -42,6 +42,11 @@
position: relative;
}
.tableRowSubComponent {
position: relative;
min-height: 100px;
}
.nameCellContainer {
align-items: center;
}
@ -53,3 +58,11 @@
.optionsMenu {
min-width: unset;
}
.activeRow {
border-color: var(--primary-7) !important;
:global(.TableV2--cells) {
background-color: var(--primary-1) !important;
border: 1px solid var(--primary-2) !important;
}
}

View File

@ -16,8 +16,10 @@
/* eslint-disable */
// This is an auto-generated file
export declare const activeRow: string
export declare const cellBtn: string
export declare const nameCellContainer: string
export declare const optionsMenu: string
export declare const table: string
export declare const tableRow: string
export declare const tableRowSubComponent: string

View File

@ -14,21 +14,28 @@
* limitations under the License.
*/
import React from 'react'
import React, { useCallback } from 'react'
import classNames from 'classnames'
import type { Column } from 'react-table'
import { PaginationProps, TableV2 } from '@harnessio/uicore'
import type { Column, Row } from 'react-table'
import { Container, PaginationProps, TableV2 } from '@harnessio/uicore'
import type { ArtifactMetadata, ListArtifact } from '@harnessio/react-har-service-client'
import { useStrings } from '@ar/frameworks/strings'
import { useParentHooks } from '@ar/hooks'
import { killEvent } from '@ar/common/utils'
import { useStrings } from '@ar/frameworks/strings'
import type { RepositoryPackageType } from '@ar/common/types'
import versionFactory from '@ar/frameworks/Version/VersionFactory'
import { handleToggleExpandableRow } from '@ar/components/TableCells/utils'
import ArtifactRowSubComponentWidget from '@ar/frameworks/Version/ArtifactRowSubComponentWidget'
import {
ArtifactDeploymentsCell,
ArtifactDownloadsCell,
ArtifactListPullCommandCell,
ArtifactListVulnerabilitiesCell,
ArtifactNameCell,
LatestArtifactCell
ArtifactPackageTypeCell,
ArtifactVersionActions,
LatestArtifactCell,
ToggleAccordionCell
} from './ArtifactListTableCell'
import { RepositoryNameCell } from '../RegistryArtifactListTable/RegistryArtifactListTableCell'
import css from './ArtifactListTable.module.scss'
@ -47,9 +54,22 @@ export interface ArtifactListTableProps extends ArtifactListColumnActions {
export default function ArtifactListTable(props: ArtifactListTableProps): JSX.Element {
const { data, gotoPage, onPageSizeChange, sortBy, setSortBy } = props
const [expandedRows, setExpandedRows] = React.useState<Set<string>>(new Set())
const { useDefaultPaginationProps } = useParentHooks()
const { getString } = useStrings()
const getRowId = (rowData: ArtifactMetadata) => {
return `${rowData.registryIdentifier}/${rowData.name}:${rowData.version}`
}
const onToggleRow = useCallback((rowData: ArtifactMetadata): void => {
const value = getRowId(rowData)
const repositoryType = versionFactory?.getVersionType(rowData.packageType)
if (!repositoryType?.getHasArtifactRowSubComponent()) return
setExpandedRows(handleToggleExpandableRow(value))
}, [])
const { artifacts = [], itemCount = 0, pageCount = 0, pageIndex, pageSize = 0 } = data || {}
const paginationProps = useDefaultPaginationProps({
itemCount,
@ -73,6 +93,16 @@ export default function ArtifactListTable(props: ArtifactListTableProps): JSX.El
}
}
return [
{
Header: '',
accessor: 'select',
id: 'rowSelectOrExpander',
Cell: ToggleAccordionCell,
disableSortBy: true,
expandedRows,
setExpandedRows,
getRowId
},
{
Header: getString('artifactList.table.columns.artifactName'),
accessor: 'name',
@ -86,10 +116,10 @@ export default function ArtifactListTable(props: ArtifactListTableProps): JSX.El
serverSortProps: getServerSortProps('registryIdentifier')
},
{
Header: getString('artifactList.table.columns.pullCommand'),
accessor: 'pullCommand',
Cell: ArtifactListPullCommandCell,
disableSortBy: true
Header: getString('artifactList.table.columns.type'),
accessor: 'packageType',
Cell: ArtifactPackageTypeCell,
serverSortProps: getServerSortProps('packageType')
},
{
Header: getString('artifactList.table.columns.downloads'),
@ -103,20 +133,32 @@ export default function ArtifactListTable(props: ArtifactListTableProps): JSX.El
Cell: ArtifactDeploymentsCell,
disableSortBy: true
},
{
Header: getString('artifactList.table.columns.sto'),
accessor: 'sto',
Cell: ArtifactListVulnerabilitiesCell,
disableSortBy: true
},
{
Header: getString('artifactList.table.columns.lastUpdated'),
accessor: 'lastUpdated',
Cell: LatestArtifactCell,
serverSortProps: getServerSortProps('lastUpdated')
},
{
Header: '',
accessor: 'action',
Cell: ArtifactVersionActions,
disableSortBy: true
}
].filter(Boolean) as unknown as Column<ArtifactMetadata>[]
}, [currentOrder, currentSort, getString])
}, [currentOrder, currentSort, getString, expandedRows, setExpandedRows])
const renderRowSubComponent = useCallback(
({ row }: { row: Row<ArtifactMetadata> }) => (
<Container className={css.tableRowSubComponent} onClick={killEvent}>
<ArtifactRowSubComponentWidget
packageType={row.original.packageType as RepositoryPackageType}
data={row.original}
/>
</Container>
),
[]
)
return (
<TableV2<ArtifactMetadata>
@ -125,7 +167,10 @@ export default function ArtifactListTable(props: ArtifactListTableProps): JSX.El
data={artifacts}
pagination={paginationProps}
sortable
getRowClassName={() => css.tableRow}
renderRowSubComponent={renderRowSubComponent}
getRowClassName={row => classNames(css.tableRow, { [css.activeRow]: expandedRows.has(getRowId(row.original)) })}
onRowClick={onToggleRow}
autoResetExpanded={false}
/>
)
}

View File

@ -21,16 +21,18 @@ import { Link } from 'react-router-dom'
import { Position } from '@blueprintjs/core'
import { Color, FontVariation } from '@harnessio/design-system'
import { Button, ButtonVariation, Layout, Text } from '@harnessio/uicore'
import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance } from 'react-table'
import type { ArtifactMetadata, StoDigestMetadata } from '@harnessio/react-har-service-client'
import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance, UseExpandedRowProps } from 'react-table'
import { useRoutes } from '@ar/hooks'
import TableCells from '@ar/components/TableCells/TableCells'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import LabelsPopover from '@ar/components/LabelsPopover/LabelsPopover'
import RepositoryIcon from '@ar/frameworks/RepositoryStep/RepositoryIcon'
import { useStrings } from '@ar/frameworks/strings'
import { getShortDigest } from '@ar/pages/digest-list/utils'
import TableCells from '@ar/components/TableCells/TableCells'
import versionFactory from '@ar/frameworks/Version/VersionFactory'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import LabelsPopover from '@ar/components/LabelsPopover/LabelsPopover'
import { useGetRepositoryTypes } from '@ar/hooks/useGetRepositoryTypes'
import RepositoryIcon from '@ar/frameworks/RepositoryStep/RepositoryIcon'
import VersionActionsWidget from '@ar/frameworks/Version/VersionActionsWidget'
import { VersionDetailsTab } from '@ar/pages/version-details/components/VersionDetailsTabs/constants'
@ -49,6 +51,32 @@ type ArtifactNameCellActionProps = {
onClickLabel: (val: string) => void
}
export type ArtifactListExpandedColumnProps = {
expandedRows: Set<string>
setExpandedRows: React.Dispatch<React.SetStateAction<Set<string>>>
getRowId: (rowData: ArtifactMetadata) => string
}
export const ToggleAccordionCell: Renderer<{
row: UseExpandedRowProps<ArtifactMetadata> & Row<ArtifactMetadata>
column: ColumnInstance<ArtifactMetadata> & ArtifactListExpandedColumnProps
}> = ({ row, column }) => {
const { expandedRows, setExpandedRows, getRowId } = column
const data = row.original
const repositoryType = versionFactory?.getVersionType(data.packageType)
if (!repositoryType?.getHasArtifactRowSubComponent()) return <></>
return (
<TableCells.ToggleAccordionCell
expandedRows={expandedRows}
setExpandedRows={setExpandedRows}
value={getRowId(data)}
initialIsExpanded={row.isExpanded}
getToggleRowExpandedProps={row.getToggleRowExpandedProps}
onToggleRowExpanded={row.toggleRowExpanded}
/>
)
}
export const ArtifactNameCell: Renderer<{
row: Row<ArtifactMetadata>
column: ColumnInstance<ArtifactMetadata> & ArtifactNameCellActionProps
@ -57,7 +85,6 @@ export const ArtifactNameCell: Renderer<{
const { onClickLabel } = column
const routes = useRoutes()
const { name: value, version, packageType, registryIdentifier } = original
return (
<Layout.Vertical>
<TableCells.LinkCell
@ -96,6 +123,17 @@ export const ArtifactDownloadsCell: CellType = ({ value }) => {
return <TableCells.CountCell value={value} icon="download-box" iconProps={{ size: 12 }} />
}
export const ArtifactPackageTypeCell: CellType = ({ value }) => {
const repositoryTypes = useGetRepositoryTypes()
const { getString } = useStrings()
const typeConfig = repositoryTypes.find(type => type.value === value)
return <TableCells.TextCell value={typeConfig ? getString(typeConfig.label) : value} />
}
export const ArtifactSizeCell: CellType = ({ value }) => {
return <TableCells.TextCell value={value} />
}
export const ArtifactDeploymentsCell: CellType = ({ row }) => {
const { original } = row
const { deploymentMetadata } = original

View File

@ -18,6 +18,8 @@ table:
environments: Environments
sto: Security Vulnerabilities
lastUpdated: Uploaded At
size: Size
type: Type
actions:
editRepository: Edit Registry
deleteRepository: Delete Registry

View File

@ -60,7 +60,14 @@ export default function DigestListPage(props: DigestListPageProps): JSX.Element
messageTitle: getString('digestList.table.noDigestTitle'),
message: getString('digestList.table.aboutDigest')
}}>
{responseData && <DigestListTable version={version} data={responseData} />}
{responseData && (
<DigestListTable
repositoryIdentifier={repoKey}
artifactIdentifier={artifact}
versionIdentifier={version}
data={responseData}
/>
)}
</Page.Body>
)
}

View File

@ -24,6 +24,7 @@ import { useStrings } from '@ar/frameworks/strings/String'
import {
DigestActionsCell,
DigestNameCell,
type DigestNameColumnProps,
DigestVulnerabilityCell,
DownloadsCell,
OsArchCell,
@ -32,13 +33,12 @@ import {
} from './DigestTableCells'
import css from './DigestListTable.module.scss'
interface DigestListTableProps {
interface DigestListTableProps extends DigestNameColumnProps {
data: DockerManifestDetails[]
version: string
}
export default function DigestListTable(props: DigestListTableProps): JSX.Element {
const { data, version } = props
const { data, repositoryIdentifier, artifactIdentifier, versionIdentifier } = props
const { getString } = useStrings()
@ -48,7 +48,9 @@ export default function DigestListTable(props: DigestListTableProps): JSX.Elemen
Header: getString('digestList.table.columns.digest'),
accessor: 'digest',
Cell: DigestNameCell,
version
repositoryIdentifier,
artifactIdentifier,
versionIdentifier
},
{
Header: getString('digestList.table.columns.osArch'),
@ -73,8 +75,7 @@ export default function DigestListTable(props: DigestListTableProps): JSX.Elemen
{
Header: getString('digestList.table.columns.scanStatus'),
accessor: 'scanStatus',
Cell: DigestVulnerabilityCell,
version
Cell: DigestVulnerabilityCell
},
{
Header: '',
@ -83,7 +84,7 @@ export default function DigestListTable(props: DigestListTableProps): JSX.Elemen
disableSortBy: true
}
].filter(Boolean) as unknown as Column<DockerManifestDetails>[]
}, [getString, version])
}, [getString, repositoryIdentifier, artifactIdentifier, versionIdentifier])
return (
<TableV2<DockerManifestDetails>
minimal

View File

@ -20,10 +20,9 @@ import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance } fr
import type { DockerManifestDetails } from '@harnessio/react-har-service-client'
import { useStrings } from '@ar/frameworks/strings'
import { useDecodedParams, useRoutes } from '@ar/hooks'
import { useRoutes } from '@ar/hooks'
import { getShortDigest } from '@ar/pages/digest-list/utils'
import TableCells from '@ar/components/TableCells/TableCells'
import type { ArtifactDetailsPathParams } from '@ar/routes/types'
import { VersionDetailsTab } from '@ar/pages/version-details/components/VersionDetailsTabs/constants'
type CellTypeWithActions<D extends Record<string, any>, V = any> = TableInstance<D> & {
@ -35,8 +34,10 @@ type CellTypeWithActions<D extends Record<string, any>, V = any> = TableInstance
type CellType = Renderer<CellTypeWithActions<DockerManifestDetails>>
type DigestNameColumnProps = {
version: string
export type DigestNameColumnProps = {
repositoryIdentifier: string
artifactIdentifier: string
versionIdentifier: string
}
export const DigestNameCell: Renderer<{
@ -44,15 +45,14 @@ export const DigestNameCell: Renderer<{
column: ColumnInstance<DockerManifestDetails> & DigestNameColumnProps
}> = ({ row, column }) => {
const { original } = row
const { version } = column
const { repositoryIdentifier, artifactIdentifier, versionIdentifier } = column
const value = original.digest
const pathParams = useDecodedParams<ArtifactDetailsPathParams>()
const routes = useRoutes()
const linkTo = routes.toARVersionDetailsTab({
repositoryIdentifier: pathParams.repositoryIdentifier,
artifactIdentifier: pathParams.artifactIdentifier,
versionIdentifier: version,
repositoryIdentifier,
artifactIdentifier,
versionIdentifier,
versionTab: VersionDetailsTab.OVERVIEW
})
return <TableCells.LinkCell label={getShortDigest(value)} linkTo={`${linkTo}?digest=${value}`} />

View File

@ -18,11 +18,13 @@ import React from 'react'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import DigestListPage from '@ar/pages/digest-list/DigestListPage'
import ArtifactActions from '@ar/pages/artifact-details/components/ArtifactActions/ArtifactActions'
import DockerVersionListTable from '@ar/pages/version-list/DockerVersion/VersionListTable/DockerVersionListTable'
import {
type ArtifactActionProps,
ArtifactRowSubComponentProps,
type VersionActionProps,
type VersionDetailsHeaderProps,
type VersionDetailsTabProps,
@ -39,9 +41,11 @@ import DockerArtifactSecurityTestsContent from './DockerArtifactSecurityTestsCon
import DockerVersionOSSContent from './DockerVersionOSSContent/DockerVersionOSSContent'
import DockerDeploymentsContent from './DockerDeploymentsContent/DockerDeploymentsContent'
import VersionActions from '../components/VersionActions/VersionActions'
import { VersionAction } from '../components/VersionActions/types'
export class DockerVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.DOCKER
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -50,6 +54,16 @@ export class DockerVersionType extends VersionStep<ArtifactVersionSummary> {
VersionDetailsTab.DEPLOYMENTS,
VersionDetailsTab.CODE
]
protected allowedActionsOnVersion = [
VersionAction.Delete,
VersionAction.SetupClient,
VersionAction.DownloadCommand,
VersionAction.ViewVersionDetails
]
protected allowedActionsOnVersionDetailsPage = [VersionAction.Delete]
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <DockerVersionListTable {...props} />
}
@ -82,6 +96,14 @@ export class DockerVersionType extends VersionStep<ArtifactVersionSummary> {
}
renderVersionActions(props: VersionActionProps): JSX.Element {
return <VersionActions {...props} />
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element {
return (
<DigestListPage repoKey={props.data.registryIdentifier} artifact={props.data.name} version={props.data.version} />
)
}
}

View File

@ -18,6 +18,7 @@ import React from 'react'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import {
type ArtifactActionProps,
ArtifactRowSubComponentProps,
type VersionActionProps,
type VersionDetailsHeaderProps,
type VersionDetailsTabProps,
@ -25,7 +26,7 @@ import {
VersionStep
} from '@ar/frameworks/Version/Version'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import VersionListTable, {
type CommonVersionListTableProps
} from '@ar/pages/version-list/components/VersionListTable/VersionListTable'
@ -35,9 +36,14 @@ import GenericOverviewPage from './pages/overview/OverviewPage'
import OSSContentPage from './pages/oss-details/OSSContentPage'
import GenericArtifactDetailsPage from './pages/artifact-details/GenericArtifactDetailsPage'
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import VersionActions from '../components/VersionActions/VersionActions'
import { VersionAction } from '../components/VersionActions/types'
export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.GENERIC
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -52,6 +58,9 @@ export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
// [VersionListColumnEnum.Actions]: { width: '10%' } // TODO: will add this once BE support actions
}
protected allowedActionsOnVersion = [VersionAction.SetupClient, VersionAction.ViewVersionDetails]
protected allowedActionsOnVersionDetailsPage = []
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <VersionListTable {...props} columnConfigs={this.versionListTableColumnConfig} />
}
@ -77,7 +86,21 @@ export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
return <></>
}
renderVersionActions(_props: VersionActionProps): JSX.Element {
return <></>
renderVersionActions(props: VersionActionProps): JSX.Element {
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element {
return (
<VersionFilesProvider
repositoryIdentifier={props.data.registryIdentifier}
artifactIdentifier={props.data.name}
versionIdentifier={props.data.version}
shouldUseLocalParams>
<ArtifactFilesContent minimal />
</VersionFilesProvider>
)
}
}

View File

@ -18,7 +18,7 @@ import React from 'react'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import { VersionListColumnEnum } from '@ar/pages/version-list/components/VersionListTable/types'
import VersionListTable, {
CommonVersionListTableProps
@ -38,9 +38,11 @@ import HelmArtifactDetailsContent from './HelmArtifactDetailsContent'
import VersionActions from '../components/VersionActions/VersionActions'
import HelmVersionOSSContent from './HelmVersionOSSContent/HelmVersionOSSContent'
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import { VersionAction } from '../components/VersionActions/types'
export class HelmVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.HELM
protected hasArtifactRowSubComponent = false
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -55,6 +57,15 @@ export class HelmVersionType extends VersionStep<ArtifactVersionSummary> {
[VersionListColumnEnum.Actions]: { width: '10%' }
}
protected allowedActionsOnVersion = [
VersionAction.Delete,
VersionAction.SetupClient,
VersionAction.DownloadCommand,
VersionAction.ViewVersionDetails
]
protected allowedActionsOnVersionDetailsPage = [VersionAction.Delete]
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <VersionListTable {...props} columnConfigs={this.versionListTableColumnConfig} />
}
@ -81,6 +92,12 @@ export class HelmVersionType extends VersionStep<ArtifactVersionSummary> {
}
renderVersionActions(props: VersionActionProps): JSX.Element {
return <VersionActions {...props} />
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(): JSX.Element {
return <></>
}
}

View File

@ -18,13 +18,14 @@ import React from 'react'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import { VersionListColumnEnum } from '@ar/pages/version-list/components/VersionListTable/types'
import VersionListTable, {
type CommonVersionListTableProps
} from '@ar/pages/version-list/components/VersionListTable/VersionListTable'
import {
type ArtifactActionProps,
ArtifactRowSubComponentProps,
type VersionActionProps,
type VersionDetailsHeaderProps,
type VersionDetailsTabProps,
@ -33,13 +34,18 @@ import {
} from '@ar/frameworks/Version/Version'
import OSSContentPage from './pages/oss-details/OSSContentPage'
import VersionFilesProvider from '../context/VersionFilesProvider'
import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
import MavenArtifactOverviewPage from './pages/overview/MavenArtifactOverviewPage'
import MavenArtifactDetailsPage from './pages/artifact-details/MavenArtifactDetailsPage'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionActions from '../components/VersionActions/VersionActions'
import { VersionAction } from '../components/VersionActions/types'
export class MavenVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.MAVEN
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -54,6 +60,9 @@ export class MavenVersionType extends VersionStep<ArtifactVersionSummary> {
// [VersionListColumnEnum.Actions]: { width: '10%' } // TODO: will add this once BE support actions
}
protected allowedActionsOnVersion = [VersionAction.SetupClient, VersionAction.ViewVersionDetails]
protected allowedActionsOnVersionDetailsPage = []
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <VersionListTable {...props} columnConfigs={this.versionListTableColumnConfig} />
}
@ -79,7 +88,21 @@ export class MavenVersionType extends VersionStep<ArtifactVersionSummary> {
return <></>
}
renderVersionActions(_props: VersionActionProps): JSX.Element {
return <></>
renderVersionActions(props: VersionActionProps): JSX.Element {
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element {
return (
<VersionFilesProvider
repositoryIdentifier={props.data.registryIdentifier}
artifactIdentifier={props.data.name}
versionIdentifier={props.data.version}
shouldUseLocalParams>
<ArtifactFilesContent minimal />
</VersionFilesProvider>
)
}
}

View File

@ -175,7 +175,7 @@ export const mockMavenArtifactFiles: FileDetailResponseResponse = {
}
],
itemCount: 4,
pageCount: 1,
pageCount: 10,
pageIndex: 0,
pageSize: 50,
status: 'SUCCESS'

View File

@ -19,7 +19,7 @@ import { Layout } from '@harnessio/uicore'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import { VersionListColumnEnum } from '@ar/pages/version-list/components/VersionListTable/types'
import ArtifactActions from '@ar/pages/artifact-details/components/ArtifactActions/ArtifactActions'
import VersionListTable, {
@ -27,6 +27,7 @@ import VersionListTable, {
} from '@ar/pages/version-list/components/VersionListTable/VersionListTable'
import {
type ArtifactActionProps,
ArtifactRowSubComponentProps,
type VersionActionProps,
type VersionDetailsHeaderProps,
type VersionDetailsTabProps,
@ -39,9 +40,13 @@ import NpmVersionOverviewPage from './pages/overview/NpmVersionOverviewPage'
import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
import NpmVersionArtifactDetailsPage from './pages/artifact-dertails/NpmVersionArtifactDetailsPage'
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import { VersionAction } from '../components/VersionActions/types'
export class NpmVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.NPM
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -57,6 +62,14 @@ export class NpmVersionType extends VersionStep<ArtifactVersionSummary> {
[VersionListColumnEnum.Actions]: { width: '10%' }
}
protected allowedActionsOnVersion = [
VersionAction.SetupClient,
VersionAction.DownloadCommand,
VersionAction.ViewVersionDetails
]
protected allowedActionsOnVersionDetailsPage = []
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <VersionListTable {...props} columnConfigs={this.versionListTableColumnConfig} />
}
@ -88,6 +101,20 @@ export class NpmVersionType extends VersionStep<ArtifactVersionSummary> {
}
renderVersionActions(props: VersionActionProps): JSX.Element {
return <VersionActions {...props} />
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element {
return (
<VersionFilesProvider
repositoryIdentifier={props.data.registryIdentifier}
artifactIdentifier={props.data.name}
versionIdentifier={props.data.version}
shouldUseLocalParams>
<ArtifactFilesContent minimal />
</VersionFilesProvider>
)
}
}

View File

@ -19,7 +19,7 @@ import { Layout } from '@harnessio/uicore'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import { VersionListColumnEnum } from '@ar/pages/version-list/components/VersionListTable/types'
import ArtifactActions from '@ar/pages/artifact-details/components/ArtifactActions/ArtifactActions'
import VersionListTable, {
@ -27,6 +27,7 @@ import VersionListTable, {
} from '@ar/pages/version-list/components/VersionListTable/VersionListTable'
import {
type ArtifactActionProps,
ArtifactRowSubComponentProps,
type VersionActionProps,
type VersionDetailsHeaderProps,
type VersionDetailsTabProps,
@ -39,9 +40,13 @@ import NuGetVersionOverviewPage from './pages/overview/NuGetVersionOverviewPage'
import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
import NuGetVersionArtifactDetailsPage from './pages/artifact-dertails/NuGetVersionArtifactDetailsPage'
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import { VersionAction } from '../components/VersionActions/types'
export class NuGetVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.NUGET
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -57,6 +62,14 @@ export class NuGetVersionType extends VersionStep<ArtifactVersionSummary> {
[VersionListColumnEnum.Actions]: { width: '10%' }
}
protected allowedActionsOnVersion: VersionAction[] = [
VersionAction.SetupClient,
VersionAction.DownloadCommand,
VersionAction.ViewVersionDetails
]
protected allowedActionsOnVersionDetailsPage = []
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <VersionListTable {...props} columnConfigs={this.versionListTableColumnConfig} />
}
@ -88,6 +101,20 @@ export class NuGetVersionType extends VersionStep<ArtifactVersionSummary> {
}
renderVersionActions(props: VersionActionProps): JSX.Element {
return <VersionActions {...props} />
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element {
return (
<VersionFilesProvider
repositoryIdentifier={props.data.registryIdentifier}
artifactIdentifier={props.data.name}
versionIdentifier={props.data.version}
shouldUseLocalParams>
<ArtifactFilesContent minimal />
</VersionFilesProvider>
)
}
}

View File

@ -19,7 +19,7 @@ import { Layout } from '@harnessio/uicore'
import type { ArtifactVersionSummary } from '@harnessio/react-har-service-client'
import { String } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { PageType, RepositoryPackageType } from '@ar/common/types'
import { VersionListColumnEnum } from '@ar/pages/version-list/components/VersionListTable/types'
import ArtifactActions from '@ar/pages/artifact-details/components/ArtifactActions/ArtifactActions'
import VersionListTable, {
@ -27,6 +27,7 @@ import VersionListTable, {
} from '@ar/pages/version-list/components/VersionListTable/VersionListTable'
import {
type ArtifactActionProps,
ArtifactRowSubComponentProps,
type VersionActionProps,
type VersionDetailsHeaderProps,
type VersionDetailsTabProps,
@ -39,9 +40,13 @@ import { VersionDetailsTab } from '../components/VersionDetailsTabs/constants'
import PythonVersionOverviewPage from './pages/overview/PythonVersionOverviewPage'
import PythonVersionArtifactDetailsPage from './pages/artifact-dertails/PythonVersionArtifactDetailsPage'
import VersionDetailsHeaderContent from '../components/VersionDetailsHeaderContent/VersionDetailsHeaderContent'
import VersionFilesProvider from '../context/VersionFilesProvider'
import ArtifactFilesContent from '../components/ArtifactFileListTable/ArtifactFilesContent'
import { VersionAction } from '../components/VersionActions/types'
export class PythonVersionType extends VersionStep<ArtifactVersionSummary> {
protected packageType = RepositoryPackageType.PYTHON
protected hasArtifactRowSubComponent = true
protected allowedVersionDetailsTabs: VersionDetailsTab[] = [
VersionDetailsTab.OVERVIEW,
VersionDetailsTab.ARTIFACT_DETAILS,
@ -58,6 +63,14 @@ export class PythonVersionType extends VersionStep<ArtifactVersionSummary> {
[VersionListColumnEnum.Actions]: { width: '30%' }
}
protected allowedActionsOnVersion = [
VersionAction.SetupClient,
VersionAction.DownloadCommand,
VersionAction.ViewVersionDetails
]
protected allowedActionsOnVersionDetailsPage = []
renderVersionListTable(props: VersionListTableProps): JSX.Element {
return <VersionListTable {...props} columnConfigs={this.versionListTableColumnConfig} />
}
@ -89,6 +102,20 @@ export class PythonVersionType extends VersionStep<ArtifactVersionSummary> {
}
renderVersionActions(props: VersionActionProps): JSX.Element {
return <VersionActions {...props} />
const allowedActions =
props.pageType === PageType.Table ? this.allowedActionsOnVersion : this.allowedActionsOnVersionDetailsPage
return <VersionActions {...props} allowedActions={allowedActions} />
}
renderArtifactRowSubComponent(props: ArtifactRowSubComponentProps): JSX.Element {
return (
<VersionFilesProvider
repositoryIdentifier={props.data.registryIdentifier}
artifactIdentifier={props.data.name}
versionIdentifier={props.data.version}
shouldUseLocalParams>
<ArtifactFilesContent minimal />
</VersionFilesProvider>
)
}
}

View File

@ -30,7 +30,13 @@
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) 6rem minmax(0, 1fr) 15rem 10rem;
grid-template-columns: minmax(var(--har-table-name-column-min-width), 15rem) 6rem minmax(0, 1fr) 15rem 10rem !important;
}
&.minimal {
div[class*='TableV2--header'] {
--typography-color: var(--grey-500);
}
}
}

View File

@ -18,4 +18,5 @@
// This is an auto-generated file
export declare const checksumContainer: string
export declare const copyChecksumBtn: string
export declare const minimal: string
export declare const table: string

View File

@ -47,12 +47,13 @@ interface ArtifactFileListTableProps {
}
export default function ArtifactFileListTable(props: ArtifactFileListTableProps): JSX.Element {
const { data, gotoPage, onPageSizeChange, sortBy, setSortBy, className } = props
const { data, gotoPage, onPageSizeChange, sortBy, setSortBy, className, minimal } = props
const { useDefaultPaginationProps } = useParentHooks()
const { getString } = useStrings()
const { files, itemCount = 0, pageCount = 0, pageIndex, pageSize = 0 } = data
const paginationProps = useDefaultPaginationProps({
showPagination: pageCount > 1,
itemCount,
pageSize,
pageCount,
@ -111,11 +112,14 @@ export default function ArtifactFileListTable(props: ArtifactFileListTableProps)
return (
<TableV2
className={classNames(css.table, className)}
className={classNames(css.table, className, {
[css.minimal]: minimal
})}
columns={columns}
data={files as FileDetail[]}
pagination={paginationProps}
sortable
minimal={minimal}
/>
)
}

View File

@ -0,0 +1,40 @@
/*
* 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, { useContext } from 'react'
import { DEFAULT_PAGE_INDEX } from '@ar/constants'
import { VersionFilesContext } from '@ar/pages/version-details/context/VersionFilesProvider'
import ArtifactFileListTable from '@ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable'
interface ArtifactFilesContentProps {
minimal?: boolean
}
export default function ArtifactFilesContent(props: ArtifactFilesContentProps): JSX.Element {
const { minimal } = props
const { data, updateQueryParams, sort } = useContext(VersionFilesContext)
return (
<ArtifactFileListTable
data={data}
gotoPage={pageNumber => updateQueryParams({ page: pageNumber })}
setSortBy={sortArr => {
updateQueryParams({ sort: sortArr, page: DEFAULT_PAGE_INDEX })
}}
sortBy={sort}
minimal={minimal}
/>
)
}

View File

@ -15,13 +15,18 @@
*/
import React, { useState } from 'react'
import { get } from 'lodash-es'
import { PageType } from '@ar/common/types'
import { useRoutes } from '@ar/hooks'
import { useStrings } from '@ar/frameworks/strings'
import ActionButton from '@ar/components/ActionButton/ActionButton'
import CopyMenuItem from '@ar/components/MenuItemTypes/CopyMenuItem'
import LinkMenuItem from '@ar/components/MenuItemTypes/LinkMenuItem'
import type { VersionActionProps } from './types'
import SetupClientMenuItem from './SetupClientMenuItem'
import DeleteVersionMenuItem from './DeleteVersionMenuItem'
import { type VersionActionProps, VersionAction } from './types'
import { VersionDetailsTab } from '../VersionDetailsTabs/constants'
export default function VersionActions({
data,
@ -30,24 +35,37 @@ export default function VersionActions({
versionKey,
pageType,
readonly,
onClose
onClose,
allowedActions
}: VersionActionProps): JSX.Element {
const [open, setOpen] = useState(false)
const routes = useRoutes()
const { getString } = useStrings()
const isAllowed = (action: VersionAction): boolean => {
if (!allowedActions) return true
return allowedActions.includes(action)
}
if (Array.isArray(allowedActions) && allowedActions.length === 0) return <></>
return (
<ActionButton isOpen={open} setOpen={setOpen}>
<DeleteVersionMenuItem
artifactKey={artifactKey}
repoKey={repoKey}
versionKey={versionKey}
data={data}
pageType={pageType}
readonly={readonly}
onClose={() => {
setOpen(false)
onClose?.()
}}
/>
{pageType === PageType.Table && (
{isAllowed(VersionAction.Delete) && (
<DeleteVersionMenuItem
artifactKey={artifactKey}
repoKey={repoKey}
versionKey={versionKey}
data={data}
pageType={pageType}
readonly={readonly}
onClose={() => {
setOpen(false)
onClose?.()
}}
/>
)}
{isAllowed(VersionAction.SetupClient) && (
<SetupClientMenuItem
data={data}
pageType={pageType}
@ -58,6 +76,20 @@ export default function VersionActions({
repoKey={repoKey}
/>
)}
{isAllowed(VersionAction.DownloadCommand) && (
<CopyMenuItem value={get(data, 'pullCommand', '')} onCopy={() => setOpen(false)} />
)}
{isAllowed(VersionAction.ViewVersionDetails) && (
<LinkMenuItem
to={routes.toARVersionDetailsTab({
repositoryIdentifier: repoKey,
artifactIdentifier: artifactKey,
versionIdentifier: versionKey,
versionTab: VersionDetailsTab.OVERVIEW
})}>
{getString('view')}
</LinkMenuItem>
)}
</ActionButton>
)
}

View File

@ -25,4 +25,12 @@ export interface VersionActionProps {
pageType: PageType
readonly?: boolean
onClose?: () => void
allowedActions?: VersionAction[]
}
export enum VersionAction {
Delete = 'delete',
SetupClient = 'setupClient',
DownloadCommand = 'downloadCommand',
ViewVersionDetails = 'viewVersionDetails'
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import React, { createContext, type PropsWithChildren } from 'react'
import React, { createContext, useState, type PropsWithChildren } from 'react'
import { PageError, PageSpinner } from '@harnessio/uicore'
import { type FileDetailResponseResponse, useGetArtifactFilesQuery } from '@harnessio/react-har-service-client'
@ -22,6 +22,7 @@ import { encodeRef } from '@ar/hooks/useGetSpaceRef'
import type { VersionDetailsPathParams } from '@ar/routes/types'
import { useDecodedParams, useGetSpaceRef, useParentHooks } from '@ar/hooks'
import type { UseUpdateQueryParamsReturn } from '@ar/__mocks__/hooks/useUpdateQueryParams'
import { DEFAULT_ARTIFACT_LIST_TABLE_SORT, DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE } from '@ar/constants'
import {
ArtifactFileListPageQueryParams,
@ -31,23 +32,36 @@ import {
interface VersionFilesProviderProps {
data: FileDetailResponseResponse
updateQueryParams: UseUpdateQueryParamsReturn<Partial<ArtifactFileListPageQueryParams>>['updateQueryParams']
queryParams: ArtifactFileListPageQueryParams
queryParams: Partial<ArtifactFileListPageQueryParams>
refetch: () => void
sort: string[]
}
export const VersionFilesContext = createContext<VersionFilesProviderProps>({} as VersionFilesProviderProps)
const VersionFilesProvider = (props: PropsWithChildren<unknown>) => {
interface IVersionFilesProviderProps {
shouldUseLocalParams?: boolean
repositoryIdentifier?: string
artifactIdentifier?: string
versionIdentifier?: string
}
const VersionFilesProvider = (props: PropsWithChildren<IVersionFilesProviderProps>) => {
const { shouldUseLocalParams, artifactIdentifier, versionIdentifier, repositoryIdentifier } = props
const [localParams, setLocalParams] = useState<Partial<ArtifactFileListPageQueryParams>>({
page: DEFAULT_PAGE_INDEX,
size: DEFAULT_PAGE_SIZE,
sort: DEFAULT_ARTIFACT_LIST_TABLE_SORT
})
const pathParams = useDecodedParams<VersionDetailsPathParams>()
const spaceRef = useGetSpaceRef()
const spaceRef = useGetSpaceRef(repositoryIdentifier)
const { useQueryParams, useUpdateQueryParams } = useParentHooks()
const { updateQueryParams } = useUpdateQueryParams<Partial<ArtifactFileListPageQueryParams>>()
const queryParamOptions = useArtifactFileListQueryParamOptions()
const queryParams = useQueryParams<ArtifactFileListPageQueryParams>(queryParamOptions)
const { page, size, sort } = queryParams
const { page, size, sort } = shouldUseLocalParams ? localParams : queryParams
const [sortField, sortOrder] = sort || []
@ -58,8 +72,8 @@ const VersionFilesProvider = (props: PropsWithChildren<unknown>) => {
refetch
} = useGetArtifactFilesQuery({
registry_ref: spaceRef,
artifact: encodeRef(pathParams.artifactIdentifier),
version: pathParams.versionIdentifier,
artifact: encodeRef(artifactIdentifier ?? pathParams.artifactIdentifier),
version: versionIdentifier ?? pathParams.versionIdentifier,
queryParams: {
page,
size,
@ -74,7 +88,14 @@ const VersionFilesProvider = (props: PropsWithChildren<unknown>) => {
{loading ? <PageSpinner /> : null}
{error && !loading ? <PageError message={error.message} onClick={() => refetch()} /> : null}
{!error && !loading && responseData ? (
<VersionFilesContext.Provider value={{ data: responseData, refetch, updateQueryParams, queryParams, sort }}>
<VersionFilesContext.Provider
value={{
data: responseData,
refetch,
updateQueryParams: shouldUseLocalParams ? setLocalParams : updateQueryParams,
queryParams: shouldUseLocalParams ? localParams : queryParams,
sort: sort || []
}}>
{props.children}
</VersionFilesContext.Provider>
) : null}

View File

@ -61,6 +61,7 @@ actions:
scan: Scan
setupClient: Set Up Client
executions: Executions
copyCommand: Copy Command
cleanupPolicy:
name: Cleanup Policy Name
addBtn: Add Cleanup Policy

View File

@ -39,8 +39,10 @@ export interface StringsMap {
'artifactList.table.columns.name': string
'artifactList.table.columns.pullCommand': string
'artifactList.table.columns.repository': string
'artifactList.table.columns.size': string
'artifactList.table.columns.sto': string
'artifactList.table.columns.tags': string
'artifactList.table.columns.type': string
'artifactList.table.latestVersions': string
'artifactList.table.noArtifactsTitle': string
'artifactList.viewArtifactDetails': string
@ -297,6 +299,7 @@ export interface StringsMap {
'webhookList.webhookCreated': string
'webhookList.webhookDeleted': string
'webhookList.webhookUpdated': string
'actions.copyCommand': string
'actions.delete': string
'actions.edit': string
'actions.executions': string