import { Badge, Box, Flex, H1, Skeleton, styled, Text } from '@traefiklabs/faency' import { useMemo } from 'react' import { Helmet } from 'react-helmet-async' import { FiGlobe, FiInfo, FiShield } from 'react-icons/fi' import { useParams } from 'react-router-dom' import ProviderIcon from 'components/icons/providers' import { BooleanState, Chips, DetailSection, DetailSectionSkeleton, ItemBlock, ItemTitle, LayoutTwoCols, ProviderName, } from 'components/resources/DetailSections' import { ResourceStatus } from 'components/resources/ResourceStatus' import { UsedByRoutersSection, UsedByRoutersSkeleton } from 'components/resources/UsedByRoutersSection' import Tooltip from 'components/Tooltip' import { ResourceDetailDataType, ServiceDetailType, useResourceDetail } from 'hooks/use-resource-detail' import { NotFound } from 'pages/NotFound' type DetailProps = { data: ServiceDetailType protocol?: string } const SpacedColumns = styled(Flex, { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(360px, 1fr))', gridGap: '16px', }) const ServicesGrid = styled(Box, { display: 'grid', gridTemplateColumns: '2fr 1fr 1fr', alignItems: 'center', padding: '$3 $5', borderBottom: '1px solid $tableRowBorder', }) const ServersGrid = styled(Box, { display: 'grid', alignItems: 'center', padding: '$3 $5', borderBottom: '1px solid $tableRowBorder', }) const MirrorsGrid = styled(Box, { display: 'grid', gridTemplateColumns: '2fr 1fr 1fr', alignItems: 'center', padding: '$3 $5', borderBottom: '1px solid $tableRowBorder', '> *:not(:first-child)': { justifySelf: 'flex-end', }, }) const GridTitle = styled(Text, { fontSize: '14px', fontWeight: 700, color: 'hsl(0, 0%, 56%)', }) type Server = { url: string address?: string } type ServerStatus = { [server: string]: string } function getServerStatusList(data: ServiceDetailType): ServerStatus { const serversList: ServerStatus = {} data.loadBalancer?.servers?.forEach((server: Server) => { serversList[server.address || server.url] = 'DOWN' }) if (data.serverStatus) { Object.entries(data.serverStatus).forEach(([server, status]) => { serversList[server] = status }) } return serversList } export const ServicePanels = ({ data, protocol = '' }: DetailProps) => { const serversList = getServerStatusList(data) const getProviderFromName = (serviceName: string): string => { const [, provider] = serviceName.split('@') return provider || data.provider } const providerName = useMemo(() => { return data.provider }, [data.provider]) return ( } title="Service Details"> {data.type && ( {data.type} )} {data.provider && ( {providerName} )} {data.status && ( )} {data.mirroring && data.mirroring.service && ( {data.mirroring.service} )} {data.loadBalancer && ( <> {data.loadBalancer.passHostHeader && ( )} {data.loadBalancer.terminationDelay && ( {`${data.loadBalancer.terminationDelay} ms`} )} )} {data.loadBalancer?.healthCheck && ( } title="Health Check"> {data.loadBalancer.healthCheck.scheme && ( {data.loadBalancer.healthCheck.scheme} )} {data.loadBalancer.healthCheck.interval && ( {data.loadBalancer.healthCheck.interval} )} {data.loadBalancer.healthCheck.path && ( {data.loadBalancer.healthCheck.path} )} {data.loadBalancer.healthCheck.timeout && ( {data.loadBalancer.healthCheck.timeout} )} {data.loadBalancer.healthCheck.port && ( {data.loadBalancer.healthCheck.port} )} {data.loadBalancer.healthCheck.hostname && ( {data.loadBalancer.healthCheck.hostname} )} {data.loadBalancer.healthCheck.headers && ( entry.join(': '))} /> )} )} {!!data?.weighted?.services?.length && ( } title="Services" noPadding> <> Name Weight Provider {data.weighted.services.map((service) => ( {service.name} {service.weight} ))} )} {Object.keys(serversList).length > 0 && ( } title="Servers" noPadding> <> {protocol === 'http' && Status} URL {Object.entries(serversList).map(([server, status]) => ( {protocol === 'http' && } {server} ))} )} {data.mirroring?.mirrors && data.mirroring.mirrors.length > 0 && ( } title="Mirror Services" noPadding> Name Percent Provider {data.mirroring.mirrors.map((mirror) => ( {mirror.name} {mirror.percent} ))} )} ) } type HttpServiceRenderProps = { data?: ResourceDetailDataType error?: Error name: string } export const HttpServiceRender = ({ data, error, name }: HttpServiceRenderProps) => { if (error) { return ( <> {name} - Traefik Proxy Sorry, we could not fetch detail information for this Service right now. Please, try again later. ) } if (!data) { return ( <> {name} - Traefik Proxy ) } if (!data.name) { return } return ( <> {data.name} - Traefik Proxy

{data.name}

) } export const HttpService = () => { const { name } = useParams<{ name: string }>() const { data, error } = useResourceDetail(name!, 'services') return } export default HttpService