import React from 'react' ; import { Box , LinearProgress , Link } from '@material-ui/core' ; import { Entity } from '@backstage/catalog-model' ; import moment from 'moment' ; import { ARGOCD_ANNOTATION_APP_NAME , useArgoCDAppData , } from './useArgoCDAppData' ; import { InfoCard , MissingAnnotationEmptyState , Table , TableColumn , } from '@backstage/core-components' ; import { configApiRef , useApi } from '@backstage/core-plugin-api' ; import ErrorBoundary from './ErrorBoundary' ; import { isArgocdAvailable } from '../Router' ; import { ArgoCDAppDetails , ArgoCDAppList } from '../types' ; import { useAppDetails } from './useAppDetails' ; import SyncIcon from '@material-ui/icons/Sync' ; import { useEntity } from '@backstage/plugin-catalog-react' ; const getElapsedTime = ( start ) => { return moment ( start ) . fromNow ( ) ; } ; const State = ( { value } ) => { const colorMap = { Pending : '#dcbc21' , Synced : 'green' , Healthy : 'green' , Inactive : 'black' , Failed : 'red' , } ; return ( < Box display = "flex" alignItems = "center" > < span style = { { display : 'block' , width : '8px' , height : '8px' , borderRadius : '50%' , backgroundColor : colorMap [ value ] || '#dcbc21' , marginRight : '5px' , } } /> { value } < /Box>); } ; type OverviewComponentProps = { data : ArgoCDAppList ; extraColumns : TableColumn [ ] ; retry : ( ) => void ; } ; const OverviewComponent = ( { data , extraColumns , retry , } ) => { const configApi = useApi ( configApiRef ) ; const baseUrl = configApi . getOptionalString ( 'argocd.baseUrl' ) ; const columns = [ { title : 'Name' , highlight : true , render : ( row ) : React . ReactNode => baseUrl ? ( < Link href = { `${ baseUrl }/applications/${ row . metadata . name }` } target = "_blank" rel = "noopener" > { row . metadata . name } < /Link>) : (row.metadata.name), } , { title : 'Instance' , render : ( row ) : React . ReactNode => row . metadata ?. instance ?. name , } , { title : 'Sync Status' , render : ( row ) : React . ReactNode => ( < State value = { row . status . sync . status } / > ) , } , { title : 'Health Status' , render : ( row ) : React . ReactNode => ( < State value = { row . status . health . status } / > ) , } , { title : 'Last Synced' , render : ( row ) : React . ReactNode => getElapsedTime ( row . status . operationState . finishedAt ! ) , } , ] ; return ( < Table title = "ArgoCD overview" options = { { paging : false , search : false , sorting : false , draggable : false , padding : 'dense' , } } data = { data . items || [ ] } columns = { columns . concat ( extraColumns ) } actions = { [ { icon : ( ) => < SyncIcon />, tooltip : 'Refresh' , isFreeAction : true , onClick : ( ) => retry ( ) , } , ] } / > ) ; } ; const ArgoCDDetails = ( { entity , extraColumns , } ) => { const { url , appName , appSelector , projectName } = useArgoCDAppData ( { entity , } ) ; const { loading , value , error , retry } = useAppDetails ( { url , appName , appSelector , projectName , } ) ; if ( loading ) { return ( < InfoCard title = "ArgoCD overview" > < LinearProgress /> < /InfoCard>); } if ( error ) { return ( < InfoCard title = "ArgoCD overview" > Error occurred while fetching data . { error . name } : { error . message } < /InfoCard>); } if ( value ) { if ( ( value as ArgoCDAppList ) . items !== undefined ) { return ( < OverviewComponent data = { value as ArgoCDAppList } retry = { retry } extraColumns = { extraColumns } / > ) ; } if ( Array . isArray ( value ) ) { const wrapped = { items : value as Array < ArgoCDAppDetails > , } ; return ( < OverviewComponent data = { wrapped } retry = { retry } extraColumns = { extraColumns } / > ) ; } const wrapped = { items : [ value as ArgoCDAppDetails ] , } ; return ( < OverviewComponent data = { wrapped } retry = { retry } extraColumns = { extraColumns } / > ) ; } return null ; } ; type Props = { deprecated entity ? : Entity ; extraColumns ? : TableColumn [ ] ; } ; export const ArgoCDDetailsCard = ( props ) => { const { entity } = useEntity ( ) ; return ! isArgocdAvailable ( entity ) ? ( < MissingAnnotationEmptyState annotation = { ARGOCD_ANNOTATION_APP_NAME } / > ) : ( < ErrorBoundary > < ArgoCDDetails entity = { entity } extraColumns = { props . extraColumns || [ ] } / > < /ErrorBoundary>); } ;