import classnames from 'classnames' ; import { isNull } from 'lodash' ; import isUndefined from 'lodash/isUndefined' ; import { useCallback , useEffect , useState } from 'react' ; import { Channel , HelmChartType , KeptnData , Package , PackageViewsStats , RepositoryKind , SearchFiltersURL , Version as VersionData , } from '../../types' ; import RSSLinkTitle from '../common/RSSLinkTitle' ; import SeeAllModal from '../common/SeeAllModal' ; import SmallTitle from '../common/SmallTitle' ; import CapabilityLevel from './CapabilityLevel' ; import ContainerAlternativeLocations from './ContainerAlternativeLocations' ; import ContainerRegistry from './ContainerRegistry' ; import ContainersImages from './ContainersImages' ; import Dependencies from './Dependencies' ; import styles from './Details.module.css' ; import Keywords from './Keywords' ; import Last30DaysViews from './Last30DaysViews' ; import LastYearActivity from './LastYearActivity' ; import License from './License' ; import Links from './Links' ; import Maintainers from './Maintainers' ; import Platforms from './Platforms' ; import SecurityReport from './securityReport' ; import TasksInPipeline from './TasksInPipeline' ; import Version from './Version' ; import VersionInRow from './VersionInRow' ; interface Props { package : Package ; sortedVersions : VersionData [ ] ; searchUrlReferer ? : SearchFiltersURL ; fromStarredPage ? : boolean ; visibleSecurityReport : boolean ; visibleImage ? : string ; visibleTarget ? : string ; visibleSection ? : string ; channels ? : Channel [ ] | null ; eventId ? : string ; viewsStats ? : PackageViewsStats ; version ? : string ; } interface VersionsProps { items : JSX . Element [ ] ; itemsForModal : JSX . Element [ ] | JSX . Element ; } const getVersionsTitle = ( repoKind ) : string => { switch ( repoKind ) { case RepositoryKind . Helm : return 'Chart versions' ; case RepositoryKind . Container : return 'Tags' ; default : return 'Versions' ; } } ; const Details = ( props ) => { const getAllVersions = useCallback ( ( ) : VersionsProps => { let items = [ ] ; let itemsForModal = [ ] ; const getLinkedChannelToVersion = ( version ) : string | undefined => { let channelName ; if ( props . channels ) { const channel = props . channels . find ( ( ch ) => ch . version === version ) ; if ( channel ) { channelName = channel . name ; } } return channelName ; } ; props . sortedVersions . forEach ( ( av_version , index ) => { const linkedChannel = getLinkedChannelToVersion ( av_version . version ) ; items . push ( < Version key = { `${ av_version . version }_${ index }` } isActive = { av_version . version === props . package . version } { ... av_version } linkedChannel = { linkedChannel } normalizedName = { props . package . normalizedName } repository = { props . package . repository } searchUrlReferer = { props . searchUrlReferer } fromStarredPage = { props . fromStarredPage } / > ) ; itemsForModal . push ( < VersionInRow key = { `${ av_version . version }_inline_${ index }` } isActive = { av_version . version === props . package . version } { ... av_version } linkedChannel = { linkedChannel } normalizedName = { props . package . normalizedName } repository = { props . package . repository } searchUrlReferer = { props . searchUrlReferer } fromStarredPage = { props . fromStarredPage } / > ) ; } ) ; return { items , itemsForModal : ( < table className = { `table table-striped table-bordered table-sm mb-0 ${ styles . table }` } > < thead > < tr className = { styles . tableTitle } > < th scope = "col" > < span className = "px-1" > Version < /span> < /th> < th scope = "col" className = { styles . releasedCell } > < span className = "px-1" > Released < /span> < /th> < /tr> < /thead> < tbody className = { styles . body } > { itemsForModal } < /tbody> < /table>), } ; } , [ props . channels , props . fromStarredPage , props . package . normalizedName , props . package . repository , props . package . version , props . searchUrlReferer , props . sortedVersions , ] ) ; const [ versions , setVersions ] = useState < VersionsProps > ( getAllVersions ( ) ) ; useEffect ( ( ) => { setVersions ( getAllVersions ( ) ) ; } , [ props . package . version , props . package . packageId , getAllVersions ] ) ; return ( < > { ( ( ) => { switch ( props . package . repository . kind ) { case RepositoryKind . Helm : return ( < > { props . package . appVersion && ( < div > < SmallTitle text = "Application version" /> < p data - testid = "appVersion" className = "text-truncate" > { props . package . appVersion } < /p> < /div>)} < />); case RepositoryKind . Container : return ( < > < div className = "mb-3" > < SmallTitle text = "Registry" / > < ContainerRegistry url = { props . package . repository . url } /> < /div> { props . package . data && props . package . data . alternativeLocations && ( < ContainerAlternativeLocations locations = { props . package . data . alternativeLocations } />)} { props . package . appVersion && ( < div > < SmallTitle text = "Application version" / > < p data - testid = "appVersion" className = "text-truncate" > { props . package . appVersion } < /p> < /div>)} < />); default : return null ; } } ) ( ) } < div > < RSSLinkTitle title = { getVersionsTitle ( props . package . repository . kind ) } normalizedName = { props . package . normalizedName } repository = { props . package . repository } version = { props . package . version ! } / > { isUndefined ( props . package . availableVersions ) || props . package . availableVersions . length === 0 ? ( < p data - testid = "versions" > - < /p>) : (<div className="mb-3" data-testid="versions"> < SeeAllModal title = { getVersionsTitle ( props . package . repository . kind ) } { ... versions } packageId = { props . package . packageId } version = { props . package . version } / > < /div>)} < /div> < div > < LastYearActivity versions = { props . sortedVersions } /> < /div> < div > < Last30DaysViews repoKind = { props . package . repository . kind } stats = { props . viewsStats } version = { props . version } searchUrlReferer = { props . searchUrlReferer } fromStarredPage = { props . fromStarredPage } / > < /div> { ( ( ) => { switch ( props . package . repository . kind ) { case RepositoryKind . Helm : return ( < > { props . package . data && ( < > { props . package . data . type && [ HelmChartType . Application , HelmChartType . Library ] . includes ( props . package . data . type ) && ( < div > < SmallTitle text = "Type" /> < p data - testid = "chartType" className = "text-truncate" > { props . package . data . type } < /p> < /div>)} { props . package . data . kubeVersion && ( < div > < SmallTitle text = "Kubernetes version" / > < p data - testid = "kubeVersion" className = "text-truncate" > { props . package . data . kubeVersion } < /p> < /div>)} < />)} < />); case RepositoryKind . TektonTask : case RepositoryKind . TektonPipeline : return ( < > { props . package . data && props . package . data . pipelinesMinVersion && ( < div > < SmallTitle text = "Pipeline minimal version" /> < p data - testid = "appVersion" className = "text-truncate" > { props . package . data . pipelinesMinVersion } < /p> < /div>)} { props . package . data && ( < TasksInPipeline tasks = { props . package . data . tasks } kind = { props . package . repository . kind } / > ) } < />); case RepositoryKind . Keptn : const kinds = props . package . data && ! isUndefined ( props . package . data [ KeptnData . Kind ] ) && props . package . data [ KeptnData . Kind ] !== '' ? props . package . data [ KeptnData . Kind ] ! . split ( ',' ) : [ ] ; return ( < > { props . package . data && ! isUndefined ( props . package . data [ KeptnData . Version ] ) && props . package . data [ KeptnData . Version ] !== '' && ( < div > < SmallTitle text = "Keptn version" /> < p data - testid = "keptnVersion" className = "text-truncate" > { props . package . data [ KeptnData . Version ] } < /p> < /div>)} { kinds . length > 0 && ( < div > < SmallTitle text = "Kind" / > { kinds . map ( ( kind , index ) => ( < p data - testid = "keptnKind" className = { classnames ( 'text-truncate' , { 'mb-1' : index + 1 !== kinds . length } ) } key = { `keptn-kind-${ kind }` } > { kind } < /p>))} < /div>)} < />); default : return null ; } } ) ( ) } < SecurityReport repoKind = { props . package . repository . kind } disabledReport = { props . package . repository . scannerDisabled || false } allContainersImagesWhitelisted = { props . package . allContainersImagesWhitelisted || false } summary = { props . package . securityReportSummary } packageId = { props . package . packageId } version = { props . package . version ! } createdAt = { props . package . securityReportCreatedAt } visibleSecurityReport = { props . visibleSecurityReport } visibleImage = { props . visibleImage } visibleTarget = { props . visibleTarget } visibleSection = { props . visibleSection } eventId = { props . eventId } searchUrlReferer = { props . searchUrlReferer } fromStarredPage = { props . fromStarredPage } containers = { props . package . containersImages || [ ] } / > < CapabilityLevel capabilityLevel = { props . package . capabilities } /> { props . package . provider && ( < > < div > < SmallTitle text = "Provider" / > < p className = "text-truncate" > { props . package . provider } < /p> < /div> < />)} < Links links = { props . package . links } homeUrl = { props . package . homeUrl } / > < Maintainers maintainers = { props . package . maintainers } /> { props . package . license && ( < > < SmallTitle text = "License" / > < License license = { props . package . license } className = "mb-3" linkClassName = "py-1 py-sm-0 text-primary" linkContentClassName = { styles . text } visibleIcon / > < />)} < ContainersImages containers = { props . package . containersImages } packageId = { props . package . packageId } kind = { props . package . repository . kind } / > { props . package . repository . kind === RepositoryKind . Helm && ! isUndefined ( props . package . data ) && ! isNull ( props . package . data ) && ( < Dependencies dependencies = { props . package . data . dependencies } packageId = { props . package . packageId } / > ) } { props . package . data && props . package . data . platforms && ( < Platforms title = "Supported Platforms" platforms = { props . package . data . platforms } / > ) } < SmallTitle text = "Keywords" id = "keywords-list" / > < Keywords keywords = { props . package . keywords } deprecated = { props . package . deprecated } / > < />); } ; export default Details ;