Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions web/src/ar/frameworks/RepositoryStep/RegistryRefContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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, { createContext, useContext } from 'react'

/**
* Pre-computed registry ref (e.g. from list path). Set by RepositoryActionsWidget when
* opened from the registry list; consumed by RepositoryActions/UpstreamProxyActions for
* the Setup Client flow. When not set (e.g. on details page), useRegistryRef() returns
* undefined and SetupClientContent falls back to scope-based ref.
*/
const RegistryRefContext = createContext<string | undefined>(undefined)

export function RegistryRefProvider({
value,
children
}: {
value: string | undefined
children: React.ReactNode
}): React.ReactElement {
return <RegistryRefContext.Provider value={value}>{children}</RegistryRefContext.Provider>
}

export function useRegistryRef(): string | undefined {
return useContext(RegistryRefContext)
}
21 changes: 14 additions & 7 deletions web/src/ar/frameworks/RepositoryStep/RepositoryActionsWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,30 @@ import type { RepositoryPackageType } from '@ar/common/types'
import repositoryFactory from './RepositoryFactory'
import type { RepositoryAbstractFactory } from './RepositoryAbstractFactory'
import type { RepositoryActionsProps } from './Repository'
import { RegistryRefProvider } from './RegistryRefContext'

interface RepositoryActionsWidgetProps<T> extends RepositoryActionsProps<T> {
factory?: RepositoryAbstractFactory
packageType: RepositoryPackageType
/** Pre-computed registry ref from list (path). Provided via context to actions for Setup Client. */
registryRef?: string
}

export default function RepositoryActionsWidget<T>(props: RepositoryActionsWidgetProps<T>): JSX.Element {
const { factory = repositoryFactory, packageType, type, data, readonly, pageType } = props
const { factory = repositoryFactory, packageType, type, data, readonly, pageType, registryRef } = props
const { getString } = useStrings()
const repositoryType = factory?.getRepositoryType(packageType)
if (!repositoryType) {
return <Text intent="warning">{getString('stepNotFound')}</Text>
}
return repositoryType.renderActions({
data,
readonly,
type,
pageType
})
return (
<RegistryRefProvider value={registryRef}>
{repositoryType.renderActions({
data,
readonly,
type,
pageType
})}
</RegistryRefProvider>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,27 @@ import type { RepositoryAbstractFactory } from './RepositoryAbstractFactory'
interface RepositorySetupClientWidgetProps extends RepositoySetupClientProps {
factory?: RepositoryAbstractFactory
type: RepositoryPackageType
/** Pre-computed registry ref (e.g. from list). When set, used for client-setup-details API. Injected here so types don't prop-drill. */
registryRef?: string
}

export default function RepositorySetupClientWidget(props: RepositorySetupClientWidgetProps): JSX.Element {
const { factory = repositoryFactory, type, onClose, repoKey, artifactKey, versionKey } = props
const { factory = repositoryFactory, type, onClose, repoKey, artifactKey, versionKey, registryRef } = props
const { getString } = useStrings()
const repositoryType = factory?.getRepositoryType(type)
if (!repositoryType) {
return <Text intent="warning">{getString('stepNotFound')}</Text>
}
return repositoryType.renderSetupClient({
const content = repositoryType.renderSetupClient({
onClose,
repoKey,
artifactKey,
versionKey
})
if (!content || !React.isValidElement(content)) {
return content
}
return React.cloneElement(content, {
registryRef
} as React.Attributes & { registryRef?: string })
}
2 changes: 1 addition & 1 deletion web/src/ar/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export { useDecodedParams } from './useDecodedParams'
export { useLocalStorage } from './useLocalStorage'
export { useRoutes } from './useRoutes'
export { useDeepCompareEffect, useDeepCompareMemo } from './useDeepCompareEffect'
export { useGetSpaceRef } from './useGetSpaceRef'
export { useGetSpaceRef, encodeRef } from './useGetSpaceRef'
export { useParentContextObj } from './useParentContextObj'
export { useLicenseStore } from './useLicenseStore'
export { useFeatureFlags, useFeatureFlag } from './useFeatureFlag'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import React, { useState } from 'react'
import { useAllowSoftDelete } from '@ar/hooks'
import { PageType } from '@ar/common/types'
import ActionButton from '@ar/components/ActionButton/ActionButton'
import { useRegistryRef } from '@ar/frameworks/RepositoryStep/RegistryRefContext'

import SetupClientMenuItem from './SetupClient'
import type { RepositoryActionsProps } from './types'
Expand All @@ -28,6 +29,7 @@ import SoftDeleteRepositoryMenuItem from './SoftDeleteRepository'
export default function RepositoryActions({ data, readonly, pageType }: RepositoryActionsProps): JSX.Element {
const [open, setOpen] = useState(false)
const allowSoftDelete = useAllowSoftDelete()
const registryRef = useRegistryRef()
return (
<ActionButton isOpen={open} setOpen={setOpen}>
{allowSoftDelete && (
Expand All @@ -40,7 +42,13 @@ export default function RepositoryActions({ data, readonly, pageType }: Reposito
)}
<DeleteRepositoryMenuItem data={data} readonly={readonly} pageType={pageType} onClose={() => setOpen(false)} />
{pageType === PageType.Table && (
<SetupClientMenuItem data={data} readonly={readonly} pageType={pageType} onClose={() => setOpen(false)} />
<SetupClientMenuItem
data={data}
readonly={readonly}
pageType={pageType}
registryRef={registryRef}
onClose={() => setOpen(false)}
/>
)}
</ActionButton>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ import { PermissionIdentifier, ResourceType } from '@ar/common/permissionTypes'
import { useSetupClientModal } from '@ar/pages/repository-details/hooks/useSetupClientModal/useSetupClientModal'
import type { RepositoryActionsProps } from './types'

export default function SetupClientMenuItem({ data, onClose }: RepositoryActionsProps): JSX.Element {
export default function SetupClientMenuItem({ data, onClose, registryRef }: RepositoryActionsProps): JSX.Element {
const { getString } = useStrings()
const { RbacMenuItem } = useParentComponents()
const [showSetupClientModal] = useSetupClientModal({
repoKey: data.identifier,
packageType: data.packageType as RepositoryPackageType,
onClose
onClose,
registryRef
})
return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ export interface RepositoryActionsProps {
readonly: boolean
pageType: PageType
onClose?: () => void
/** Pre-computed registry ref from list (path + /+). When set, used for client-setup-details API. */
registryRef?: string
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,23 @@ interface SetupClientContentProps {
artifactKey?: string
versionKey?: string
packageType: PackageType
/** Pre-computed registry ref (e.g. from list). When set, used for client-setup-details API; otherwise use scope + repoKey. */
registryRef?: string
}

export default function SetupClientContent(props: SetupClientContentProps): JSX.Element {
const { onClose, packageType, repoKey } = props
const { onClose, packageType, repoKey, registryRef: registryRefProp } = props
const { getString } = useStrings()
const spaceRef = useGetSpaceRef(repoKey)
const spaceRefFromScope = useGetSpaceRef(repoKey)
const registryRef = registryRefProp ?? spaceRefFromScope

const {
isFetching: loading,
data,
error,
refetch
} = useGetClientSetupDetailsQuery({
registry_ref: spaceRef,
registry_ref: registryRef,
queryParams: {
artifact: props.artifactKey,
version: props.versionKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ import css from './useSetupClientModal.module.scss'
export interface useSetupClientModalProps extends Omit<RepositoySetupClientProps, 'onClose'> {
packageType: RepositoryPackageType
onClose?: () => void
/** Pre-computed registry ref (e.g. from list). When set, used for client-setup-details API. */
registryRef?: string
}

export function useSetupClientModal(props: useSetupClientModalProps) {
const { packageType, repoKey, artifactKey, versionKey, onClose } = props
const { packageType, repoKey, artifactKey, versionKey, onClose, registryRef } = props
const { useModalHook } = useParentHooks()

const [showModal, hideModal] = useModalHook(() => {
Expand Down Expand Up @@ -58,6 +60,7 @@ export function useSetupClientModal(props: useSetupClientModalProps) {
versionKey={versionKey}
onClose={handleCloseModal}
type={packageType as RepositoryPackageType}
registryRef={registryRef}
/>
</Drawer>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type { RegistryMetadata } from '@harnessio/react-har-service-client'
import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance } from 'react-table'

import ScopeBadge from '@ar/components/Badge/ScopeBadge'
import { encodeRef } from '@ar/hooks'
import { useStrings } from '@ar/frameworks/strings/String'
import TableCells from '@ar/components/TableCells/TableCells'
import { getEntityScopeType } from '@ar/hooks/useGetPageScope'
Expand Down Expand Up @@ -102,13 +103,16 @@ export const RepositoryDownloadsCell: CellType = ({ value }) => {
}

export const RepositoryActionsCell: CellType = ({ row }) => {
const { path } = row.original
const registryRef = path ? encodeRef(path) : undefined
return (
<RepositoryActionsWidget
type={row.original.type as RepositoryConfigType}
packageType={row.original.packageType as RepositoryPackageType}
data={row.original}
readonly={false}
pageType={PageType.Table}
registryRef={registryRef}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { compact as lodashCompact } from 'lodash-es'
import { Switch } from 'react-router-dom'
import { Container } from '@harnessio/uicore'

import { useAppStore, useParentHooks, useRoutes } from '@ar/hooks'
import { useAppStore, useParentHooks, useRoutes, encodeRef } from '@ar/hooks'
import { PageType } from '@ar/common/types'
import RouteProvider from '@ar/components/RouteProvider/RouteProvider'
import RepositoryProvider from '@ar/pages/repository-details/context/RepositoryProvider'
Expand Down Expand Up @@ -151,16 +151,20 @@ export default function RepositoryListTreeView() {
const { metadata } = node
const { entityType, repositoryIdentifier, artifactIdentifier, versionIdentifier } = metadata || {}
switch (entityType) {
case TreeNodeEntityEnum.REGISTRY:
case TreeNodeEntityEnum.REGISTRY: {
const path = (metadata as { path?: string })?.path
const registryRef = path ? encodeRef(path) : undefined
return (
<RepositoryActionsWidget
packageType={metadata.packageType}
data={node.metadata}
pageType={PageType.Table}
type={metadata.type}
readonly={false}
registryRef={registryRef}
/>
)
}
case TreeNodeEntityEnum.ARTIFACT:
return (
<ArtifactActionsWidget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ActionButton from '@ar/components/ActionButton/ActionButton'

import { PageType } from '@ar/common/types'
import { useAllowSoftDelete } from '@ar/hooks'
import { useRegistryRef } from '@ar/frameworks/RepositoryStep/RegistryRefContext'
import SetupClientMenuItem from '@ar/pages/repository-details/components/Actions/SetupClient'
import DeleteRepositoryMenuItem from '@ar/pages/repository-details/components/Actions/DeleteRepository'
import SoftDeleteRepositoryMenuItem from '@ar/pages/repository-details/components/Actions/SoftDeleteRepository'
Expand All @@ -28,6 +29,7 @@ import type { UpstreamProxyActionProps } from './type'
export default function UpstreamProxyActions({ data, readonly, pageType }: UpstreamProxyActionProps): JSX.Element {
const [open, setOpen] = useState(false)
const allowSoftDelete = useAllowSoftDelete()
const registryRef = useRegistryRef()
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return (
<ActionButton isOpen={open} setOpen={setOpen}>
{allowSoftDelete && (
Expand All @@ -40,7 +42,13 @@ export default function UpstreamProxyActions({ data, readonly, pageType }: Upstr
)}
<DeleteRepositoryMenuItem data={data} readonly={readonly} pageType={pageType} onClose={() => setOpen(false)} />
{pageType === PageType.Table && (
<SetupClientMenuItem data={data} readonly={readonly} pageType={pageType} onClose={() => setOpen(false)} />
<SetupClientMenuItem
data={data}
readonly={readonly}
pageType={pageType}
registryRef={registryRef}
onClose={() => setOpen(false)}
/>
)}
</ActionButton>
)
Expand Down