feat: [AH-1222]: implement tags for thumbnails in create registry and create upstream form (#3695)

* feat: [AH-1222]: add new package types as coming soon
* feat: [AH-1222]: implement tags for thumbnails in create registry and create upstream form
This commit is contained in:
Shivanand Sonnad 2025-04-17 14:38:43 +00:00 committed by Harness
parent 2d385d1137
commit e3e0af68ce
20 changed files with 329 additions and 21 deletions

View File

@ -50,11 +50,11 @@
"@codemirror/state": "^6.2.0",
"@codemirror/view": "^6.9.6",
"@harnessio/design-system": "^2.1.1",
"@harnessio/icons": "^2.1.9",
"@harnessio/icons": "^2.1.12",
"@harnessio/react-har-service-client": "^0.17.0",
"@harnessio/react-ng-manager-client": "^1.40.0",
"@harnessio/react-ssca-manager-client": "^0.65.0",
"@harnessio/uicore": "^4.1.2",
"@harnessio/uicore": "^4.2.0",
"@tanstack/react-query": "4.20.4",
"@types/dompurify": "^3.0.2",
"@types/react-monaco-editor": "^0.16.0",

View File

@ -52,7 +52,12 @@ export enum RepositoryPackageType {
NPM = 'NPM',
GRADLE = 'GRADLE',
PYTHON = 'PYTHON',
NUGET = 'NUGET'
NUGET = 'NUGET',
RPM = 'RPM',
GO = 'GO',
DEBIAN = 'DEBIAN',
RUST = 'RUST',
ALPINE = 'ALPINE'
}
export enum RepositoryConfigType {

View File

@ -33,9 +33,28 @@
}
.tag {
font-size: 10px;
font-size: var(--font-size-xsmall);
font-weight: 700;
line-height: 15px;
border-radius: 4px;
}
.newTag {
background-color: var(--primary-2) !important;
border-color: var(--primary-2) !important;
color: var(--primary-7) !important;
}
.comingSoonTag {
background-color: var(--purple-50) !important;
border-color: var(--purple-50) !important;
color: var(--purple-800) !important;
}
.betaTag {
background-color: var(--yellow-200) !important;
border-color: var(--yellow-200) !important;
color: var(--orange-800) !important;
}
.prodTag {

View File

@ -17,6 +17,9 @@
/* eslint-disable */
// This is an auto-generated file
export declare const artifactTag: string
export declare const betaTag: string
export declare const comingSoonTag: string
export declare const newTag: string
export declare const nonProdTag: string
export declare const prodTag: string
export declare const tag: string

View File

@ -0,0 +1,52 @@
/*
* 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 { StringKeys, useStrings } from '@ar/frameworks/strings'
import Tag from './Tag'
import css from './Tag.module.scss'
export enum ThumbnailTagEnum {
Beta = 'beta',
New = 'new',
ComingSoon = 'comingSoon'
}
const TagToConfigMap: Record<ThumbnailTagEnum, { label: StringKeys; className: keyof typeof css }> = {
beta: { label: 'beta', className: 'betaTag' },
new: { label: 'new', className: 'newTag' },
comingSoon: { label: 'soon', className: 'comingSoonTag' }
}
interface ThumbnailTagsProps {
tag: ThumbnailTagEnum
className?: string
}
export function ThumbnailTags(props: ThumbnailTagsProps): JSX.Element {
const { tag, className } = props
const { getString } = useStrings()
const config = TagToConfigMap[tag]
return (
<Tag className={classNames(className, css.tag, css[config.className])} round>
{getString(config.label)}
</Tag>
)
}

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
.tag {
position: absolute;
top: -8px;
right: -8px;
}

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

View File

@ -0,0 +1,44 @@
/*
* 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 { Color } from '@harnessio/design-system'
import { ThumbnailTagEnum, ThumbnailTags } from '../Tag/ThumbnailTags'
import css from './ThumbnailLabel.module.scss'
interface ThumbnailLabelProps {
label: string
disabled?: boolean
tag?: ThumbnailTagEnum
}
export default function ThumbnailLabel(props: ThumbnailLabelProps): JSX.Element {
const { label, tag, disabled } = props
return (
<div>
<Text
font={{ size: 'small', weight: 'semi-bold' }}
color={disabled ? Color.GREY_500 : Color.GREY_600}
margin={{ top: 'small' }}>
{label}
</Text>
{tag && <ThumbnailTags className={css.tag} tag={tag} />}
</div>
)
}

View File

@ -18,6 +18,7 @@ import type { IconName } from '@harnessio/icons'
import { FeatureFlags } from '@ar/MFEAppTypes'
import type { StringsMap } from '@ar/frameworks/strings'
import { RepositoryPackageType } from '@ar/common/types'
import { ThumbnailTagEnum } from '@ar/components/Tag/ThumbnailTags'
import { useFeatureFlags } from './useFeatureFlag'
export interface RepositoryTypeListItem {
@ -27,6 +28,7 @@ export interface RepositoryTypeListItem {
disabled?: boolean
tooltip?: string
featureFlag?: FeatureFlags
tag?: ThumbnailTagEnum
}
export const useGetRepositoryTypes = (): RepositoryTypeListItem[] => {
@ -68,12 +70,14 @@ const RepositoryTypes: RepositoryTypeListItem[] = [
{
label: 'repositoryTypes.pypi',
value: RepositoryPackageType.PYTHON,
icon: 'python'
icon: 'python',
tag: ThumbnailTagEnum.Beta
},
{
label: 'repositoryTypes.npm',
value: RepositoryPackageType.NPM,
icon: 'npm-repository-type'
icon: 'npm-repository-type',
tag: ThumbnailTagEnum.Beta
},
{
label: 'repositoryTypes.nuget',
@ -81,6 +85,47 @@ const RepositoryTypes: RepositoryTypeListItem[] = [
icon: 'nuget-repository-type',
tooltip: 'Coming Soon!',
featureFlag: FeatureFlags.HAR_NUGET_PACKAGE_TYPE_ENABLED,
disabled: true
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.rpm',
value: RepositoryPackageType.RPM,
icon: 'red-hat-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.go',
value: RepositoryPackageType.GO,
icon: 'go-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.debian',
value: RepositoryPackageType.DEBIAN,
icon: 'debian-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.alpine',
value: RepositoryPackageType.ALPINE,
icon: 'alpine-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.rust',
value: RepositoryPackageType.RUST,
icon: 'rust-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
}
]

View File

@ -18,6 +18,7 @@ import type { IconName } from '@harnessio/icons'
import { FeatureFlags } from '@ar/MFEAppTypes'
import type { StringsMap } from '@ar/frameworks/strings'
import { ThumbnailTagEnum } from '@ar/components/Tag/ThumbnailTags'
import { UpstreamProxyPackageType } from '@ar/pages/upstream-proxy-details/types'
import { useFeatureFlags } from './useFeatureFlag'
@ -29,6 +30,7 @@ export interface UpstreamRepositoryPackageTypeListItem {
disabled?: boolean
tooltip?: string
featureFlag?: FeatureFlags
tag?: ThumbnailTagEnum
}
export const useGetUpstreamRepositoryPackageTypes = (): UpstreamRepositoryPackageTypeListItem[] => {
@ -65,12 +67,14 @@ export const UpstreamProxyPackageTypeList: UpstreamRepositoryPackageTypeListItem
{
label: 'repositoryTypes.pypi',
value: UpstreamProxyPackageType.PYTHON,
icon: 'python'
icon: 'python',
tag: ThumbnailTagEnum.Beta
},
{
label: 'repositoryTypes.npm',
value: UpstreamProxyPackageType.NPM,
icon: 'npm-repository-type'
icon: 'npm-repository-type',
tag: ThumbnailTagEnum.Beta
},
{
label: 'repositoryTypes.nuget',
@ -78,6 +82,47 @@ export const UpstreamProxyPackageTypeList: UpstreamRepositoryPackageTypeListItem
icon: 'nuget-repository-type',
tooltip: 'Coming Soon!',
featureFlag: FeatureFlags.HAR_NUGET_PACKAGE_TYPE_ENABLED,
disabled: true
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.rpm',
value: UpstreamProxyPackageType.RPM,
icon: 'red-hat-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.go',
value: UpstreamProxyPackageType.GO,
icon: 'go-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.debian',
value: UpstreamProxyPackageType.DEBIAN,
icon: 'debian-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.alpine',
value: UpstreamProxyPackageType.ALPINE,
icon: 'alpine-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
},
{
label: 'repositoryTypes.rust',
value: UpstreamProxyPackageType.RUST,
icon: 'rust-logo',
tooltip: 'Coming Soon!',
disabled: true,
tag: ThumbnailTagEnum.ComingSoon
}
]

View File

@ -44,6 +44,7 @@ import { Separator } from '@ar/components/Separator/Separator'
import type { Repository, VirtualRegistryRequest } from '@ar/pages/repository-details/types'
import { getFormattedFormDataForCleanupPolicy } from '@ar/components/CleanupPolicyList/utils'
import { useGetRepositoryTypes } from '@ar/hooks/useGetRepositoryTypes'
import ThumbnailLabel from '@ar/components/ThumbnailLabel/ThumbnailLabel'
import css from './RepositoryDetailsForm.module.scss'
@ -78,9 +79,15 @@ function FormContent(props: FormContentProps): JSX.Element {
<Container>
<ThumbnailSelect
name="packageType"
layoutProps={{
spacing: 'none',
className: css.thumbnailContainer
}}
cornerSelected={false}
thumbnailClassName={css.thumbnailCard}
items={repositoryTypes.map(each => ({
...each,
label: getString(each.label),
label: <ThumbnailLabel disabled={each.disabled} label={getString(each.label)} tag={each.tag} />,
disabled: allowedPackageTypes?.length ? !allowedPackageTypes.includes(each.value) : each.disabled
}))}
staticItems

View File

@ -19,6 +19,15 @@
background-color: #fafcff !important;
}
.thumbnailContainer {
flex-wrap: wrap;
gap: var(--spacing-medium);
}
.thumbnailCard {
position: relative;
}
.formContainer {
:global(.bp3-form-group .bp3-input),
:global(.bp3-form-group .bp3-input-group),

View File

@ -18,3 +18,5 @@
// This is an auto-generated file
export declare const formContainer: string
export declare const pageBody: string
export declare const thumbnailCard: string
export declare const thumbnailContainer: string

View File

@ -26,3 +26,12 @@
--page-header-height: 100px;
background-color: #fafcff !important;
}
.thumbnailContainer {
flex-wrap: wrap;
gap: var(--spacing-medium);
}
.thumbnailCard {
position: relative;
}

View File

@ -18,3 +18,5 @@
// This is an auto-generated file
export declare const formContainer: string
export declare const pageBody: string
export declare const thumbnailCard: string
export declare const thumbnailContainer: string

View File

@ -42,6 +42,7 @@ import {
UpstreamRegistryRequest
} from '@ar/pages/upstream-proxy-details/types'
import ThumbnailLabel from '@ar/components/ThumbnailLabel/ThumbnailLabel'
import CreateRepositoryWidget from '@ar/frameworks/RepositoryStep/CreateRepositoryWidget'
import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory'
import { getFormattedFormDataForCleanupPolicy } from '@ar/components/CleanupPolicyList/utils'
@ -77,9 +78,15 @@ function FormContent(props: FormContentProps): JSX.Element {
<Container>
<ThumbnailSelect
name="packageType"
layoutProps={{
spacing: 'none',
className: css.thumbnailContainer
}}
cornerSelected={false}
thumbnailClassName={css.thumbnailCard}
items={packageTypeList.map(each => ({
...each,
label: getString(each.label)
label: <ThumbnailLabel disabled={each.disabled} label={getString(each.label)} tag={each.tag} />
}))}
staticItems
onChange={(val: UpstreamProxyPackageType) => {

View File

@ -24,7 +24,12 @@ export enum UpstreamProxyPackageType {
MAVEN = 'MAVEN',
NPM = 'NPM',
PYTHON = 'PYTHON',
NUGET = 'NUGET'
NUGET = 'NUGET',
RPM = 'RPM',
GO = 'GO',
DEBIAN = 'DEBIAN',
RUST = 'RUST',
ALPINE = 'ALPINE'
}
export enum UpstreamRepositoryURLInputSource {

View File

@ -22,6 +22,7 @@ dateLabel: Date
timeLabel: Time
harnessAI: Harness AI
new: NEW
beta: BETA
harLabel: '{{ $.repositoryList.artifactRegistry.label }}'
na: N/A
success: Success
@ -30,6 +31,7 @@ retriableError: Retriable Error
unknown: Unknown
cancel: Cancel
comingSoon: Coming Soon.
soon: SOON
failedToLoadData: Failed to load data. Please try again!
all: All
noResultsFound: No results found
@ -90,6 +92,11 @@ repositoryTypes:
gradle: Gradle
pypi: Python
nuget: NuGet
rpm: RPM
go: Go
debian: Debian
rust: Rust
alpine: Alpine
sideNav:
repositories: '{{ $.repositoryList.pageHeading }}'
artifacts: '{{ $.artifactList.pageHeading }}'

View File

@ -311,6 +311,7 @@ export interface StringsMap {
all: string
'badges.artifactRegistry': string
'badges.upstreamProxy': string
beta: string
'breadcrumbs.artifacts': string
'breadcrumbs.repositories': string
'breadcrumbs.upstreamProxies': string
@ -367,20 +368,26 @@ export interface StringsMap {
plusNewName: string
prod: string
prodCount: string
'repositoryTypes.alpine': string
'repositoryTypes.debian': string
'repositoryTypes.docker': string
'repositoryTypes.generic': string
'repositoryTypes.go': string
'repositoryTypes.gradle': string
'repositoryTypes.helm': string
'repositoryTypes.maven': string
'repositoryTypes.npm': string
'repositoryTypes.nuget': string
'repositoryTypes.pypi': string
'repositoryTypes.rpm': string
'repositoryTypes.rust': string
retriableError: string
save: string
search: string
'sideNav.artifacts': string
'sideNav.repositories': string
'sideNav.upstreamProxies': string
soon: string
stepNotFound: string
success: string
tabNotFound: string

View File

@ -1921,10 +1921,10 @@
resolved "https://registry.npmjs.org/@harnessio/design-system/-/design-system-2.1.1.tgz#2da3036602ed9b9446d8139c72009e6dc1e25642"
integrity sha512-ZwAGM1srOZ49/6YkwyjkczUv4v91CN0rCecRYnV3/g+xdSV5ycrUvkJjl9nHub6jw2eCGC0GdyNgAtAJnLmGfQ==
"@harnessio/icons@^2.1.9":
version "2.1.10"
resolved "https://registry.yarnpkg.com/@harnessio/icons/-/icons-2.1.10.tgz#2a849fbf41a00e2b0dac016bec74f9166e6e6fa2"
integrity sha512-LArSZWVxYUqkOM228t/fHUnws3PtVayBbqx+4zKODsbCpr4GdFDX/CIel6hpKREknk4YdfZvjeSBjvuLOw+KjQ==
"@harnessio/icons@^2.1.12":
version "2.1.12"
resolved "https://registry.yarnpkg.com/@harnessio/icons/-/icons-2.1.12.tgz#3fa50c49b8c81013ca867681bccd343fdb973c1b"
integrity sha512-FVwaIOBrc5xj2j+84j8Up1jaGuu6UsUzXcG30Td0ZEBZVqR0Lgz6KoVwIheT0uVjC3cqjvBN6+Z+Im3HrWnH0w==
"@harnessio/oats-cli@^3.0.0":
version "3.0.0"
@ -1962,10 +1962,10 @@
resolved "https://registry.yarnpkg.com/@harnessio/react-ssca-manager-client/-/react-ssca-manager-client-0.65.0.tgz#8088869e282c5268bf1fefb9715652e0fc1a8940"
integrity sha512-sNLDf1lyBfdzD9TqlrsMib61YffrEpb5WJwhRKuPGKD9Po0peAqE6NGLHVFbyra4tRGvvg8gnNpzzp4hMBYeCQ==
"@harnessio/uicore@^4.1.2":
version "4.1.2"
resolved "https://registry.npmjs.org/@harnessio/uicore/-/uicore-4.1.2.tgz#731c8da3f53531b90f5b5cde4589b248129ef306"
integrity sha512-xlV47pFpVd5LHBarMm18xgveUxoss5qpHhHAg8FKnfr6S+gy5OgfAsqWJAIiOCaUmwRbEvT/pAZeAQGh6fFUCA==
"@harnessio/uicore@^4.2.0":
version "4.2.0"
resolved "https://registry.yarnpkg.com/@harnessio/uicore/-/uicore-4.2.0.tgz#4ce930b2832fe406a91a963f417215e098e56326"
integrity sha512-jb5kRQgrrdcYfuECmk9Zn1u7K8b0L81l0HKuiZsmqOpc7dhM/zCrSc4zLTHxfmi1iUB/VULRhKnekxjU4ChpHQ==
"@humanwhocodes/config-array@^0.5.0":
version "0.5.0"