diff --git a/web/package.json b/web/package.json index 4b7dbca96..4d184b5bc 100644 --- a/web/package.json +++ b/web/package.json @@ -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", diff --git a/web/src/ar/pages/version-details/GenericVersion/GenericVersionType.tsx b/web/src/ar/pages/version-details/GenericVersion/GenericVersionType.tsx index b17df0cff..89463135b 100644 --- a/web/src/ar/pages/version-details/GenericVersion/GenericVersionType.tsx +++ b/web/src/ar/pages/version-details/GenericVersion/GenericVersionType.tsx @@ -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 { protected packageType = RepositoryPackageType.GENERIC @@ -48,7 +49,7 @@ export class GenericVersionType extends VersionStep { case VersionDetailsTab.OVERVIEW: return case VersionDetailsTab.ARTIFACT_DETAILS: - return <> + return case VersionDetailsTab.DEPLOYMENTS: return <> case VersionDetailsTab.OSS: diff --git a/web/src/ar/pages/version-details/GenericVersion/pages/artifact-details/GenericArtifactDetailsPage.tsx b/web/src/ar/pages/version-details/GenericVersion/pages/artifact-details/GenericArtifactDetailsPage.tsx new file mode 100644 index 000000000..74ca50108 --- /dev/null +++ b/web/src/ar/pages/version-details/GenericVersion/pages/artifact-details/GenericArtifactDetailsPage.tsx @@ -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>() + + const pathParams = useDecodedParams() + const queryParamOptions = useArtifactFileListQueryParamOptions() + const queryParams = useQueryParams(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 ( + refetch()}> + {response && ( + updateQueryParams({ page: pageNumber })} + setSortBy={sortArr => { + updateQueryParams({ sort: sortArr, page: DEFAULT_PAGE_INDEX }) + }} + sortBy={sort} + /> + )} + + ) +} diff --git a/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.module.scss b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.module.scss new file mode 100644 index 000000000..faddf0349 --- /dev/null +++ b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.module.scss @@ -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; + } +} diff --git a/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.module.scss.d.ts b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.module.scss.d.ts new file mode 100644 index 000000000..0099ad648 --- /dev/null +++ b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.module.scss.d.ts @@ -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 diff --git a/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.tsx b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.tsx new file mode 100644 index 000000000..4bfab92f7 --- /dev/null +++ b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactFileListTable.tsx @@ -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[] = 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[] + }, [currentOrder, currentSort, getString]) + + return ( + + ) +} diff --git a/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactListTableCells.tsx b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactListTableCells.tsx new file mode 100644 index 000000000..c012ca841 --- /dev/null +++ b/web/src/ar/pages/version-details/components/ArtifactFileListTable/ArtifactListTableCells.tsx @@ -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, V = any> = TableInstance & { + column: ColumnInstance + row: Row + cell: Cell + value: CellValue +} + +type CellType = Renderer> + +export const FileNameCell: CellType = ({ value }) => { + return +} + +export const FileSizeCell: CellType = ({ value }) => { + return +} + +export const FileChecksumListCell: CellType = ({ value }) => { + const { getString } = useStrings() + if (Array.isArray(value) && value.length) { + return ( + + {value.map(each => ( + + ))} + + ) + } + return +} + +export const FileCreatedCell: CellType = ({ value }) => { + return +} + +export const FileDownloadCommandCell: CellType = ({ value }) => { + const { getString } = useStrings() + if (!value) return + return +} diff --git a/web/src/ar/pages/version-details/components/ArtifactFileListTable/utils.ts b/web/src/ar/pages/version-details/components/ArtifactFileListTable/utils.ts new file mode 100644 index 000000000..299e080cb --- /dev/null +++ b/web/src/ar/pages/version-details/components/ArtifactFileListTable/utils.ts @@ -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 => { + 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 +} diff --git a/web/src/ar/pages/version-details/strings/strings.en.yaml b/web/src/ar/pages/version-details/strings/strings.en.yaml index 0b6e56f6f..1bc839794 100644 --- a/web/src/ar/pages/version-details/strings/strings.en.yaml +++ b/web/src/ar/pages/version-details/strings/strings.en.yaml @@ -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 diff --git a/web/src/ar/strings/types.ts b/web/src/ar/strings/types.ts index 5a5a7e1b1..fd5065ee8 100644 --- a/web/src/ar/strings/types.ts +++ b/web/src/ar/strings/types.ts @@ -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 diff --git a/web/yarn.lock b/web/yarn.lock index 6b6cd6f2e..33a9738d4 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -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"