mirror of
https://github.com/traefik/traefik.git
synced 2026-06-17 19:09:29 +03:00
Display server weight in service detail view
This commit is contained in:
+1
-1
@@ -49,7 +49,7 @@
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^14.2.1",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@traefiklabs/faency": "12.0.4",
|
||||
"@traefik-labs/faency": "12.0.7",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/react": "^18.2.0",
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { globalCss, Box, darkTheme, FaencyProvider, lightTheme } from '@traefiklabs/faency'
|
||||
import { globalCss, Box, darkTheme, FaencyProvider, lightTheme } from '@traefik-labs/faency'
|
||||
import { Suspense, useContext, useEffect } from 'react'
|
||||
import { HelmetProvider } from 'react-helmet-async'
|
||||
import { HashRouter, Navigate, Route, Routes as RouterRoutes, useLocation } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CSS, Text } from '@traefiklabs/faency'
|
||||
import { CSS, Text } from '@traefik-labs/faency'
|
||||
import { useContext } from 'react'
|
||||
|
||||
import CopyButton from 'components/buttons/CopyButton'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, styled } from '@traefiklabs/faency'
|
||||
import { Card, styled } from '@traefik-labs/faency'
|
||||
|
||||
const ScrollableCard = styled(Card, {
|
||||
width: '100%',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { motion } from 'framer-motion'
|
||||
import { FiLoader } from 'react-icons/fi'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AccessibleIcon, Button } from '@traefiklabs/faency'
|
||||
import { AccessibleIcon, Button } from '@traefik-labs/faency'
|
||||
import { FiMoon, FiSun } from 'react-icons/fi'
|
||||
|
||||
import { AutoThemeIcon } from 'components/icons/AutoThemeIcon'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Button, Flex, styled, Text } from '@traefiklabs/faency'
|
||||
import { Box, Button, Flex, styled, Text } from '@traefik-labs/faency'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import { ReactNode, useEffect } from 'react'
|
||||
import { FiX } from 'react-icons/fi'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { useContext } from 'react'
|
||||
|
||||
import { Toast } from './Toast'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Flex, Text, Tooltip as FaencyTooltip } from '@traefiklabs/faency'
|
||||
import { Button, Flex, Text, Tooltip as FaencyTooltip } from '@traefik-labs/faency'
|
||||
import { MouseEvent, ReactNode, useMemo, useState } from 'react'
|
||||
import { FiCheck, FiCopy } from 'react-icons/fi'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CSS, Text } from '@traefiklabs/faency'
|
||||
import { CSS, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import Tooltip from 'components/Tooltip'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Button, CSS, AccessibleIcon } from '@traefiklabs/faency'
|
||||
import { Flex, Button, CSS, AccessibleIcon } from '@traefik-labs/faency'
|
||||
import React, { useState } from 'react'
|
||||
import { FiCheck, FiCopy } from 'react-icons/fi'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Flex, Text } from '@traefiklabs/faency'
|
||||
import { Button, Flex, Text } from '@traefik-labs/faency'
|
||||
import { ComponentProps, ReactNode } from 'react'
|
||||
|
||||
type IconButtonProps = ComponentProps<typeof Button> & {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from '@traefiklabs/faency'
|
||||
import { Button } from '@traefik-labs/faency'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
export const ScrollTopButton = () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { styled, Flex, Label } from '@traefiklabs/faency'
|
||||
import { styled, Flex, Label } from '@traefik-labs/faency'
|
||||
import { ComponentProps } from 'react'
|
||||
|
||||
import SortIcon from 'components/icons/SortIcon'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { config, Flex } from '@traefiklabs/faency'
|
||||
import { config, Flex } from '@traefik-labs/faency'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { CustomIconProps } from 'components/icons'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CSS, Flex, VariantProps } from '@traefiklabs/faency'
|
||||
import { CSS, Flex, VariantProps } from '@traefik-labs/faency'
|
||||
import { HTMLAttributes } from 'react'
|
||||
|
||||
export type CustomIconProps = HTMLAttributes<SVGElement> & {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box } from '@traefiklabs/faency'
|
||||
import { Box } from '@traefik-labs/faency'
|
||||
import { HTMLAttributes, useMemo } from 'react'
|
||||
|
||||
import Consul from 'components/icons/providers/Consul'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, Flex, H1, Skeleton, Text } from '@traefiklabs/faency'
|
||||
import { Card, Flex, H1, Skeleton, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import MiddlewareDefinition from './MiddlewareDefinition'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Badge, CSS, Flex, styled, Text } from '@traefiklabs/faency'
|
||||
import { Badge, CSS, Flex, styled, Text } from '@traefik-labs/faency'
|
||||
import { ReactNode } from 'react'
|
||||
import { BsToggleOff, BsToggleOn } from 'react-icons/bs'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, CSS, Flex, Grid, H2, Skeleton, styled, Text } from '@traefiklabs/faency'
|
||||
import { Card, CSS, Flex, Grid, H2, Skeleton, styled, Text } from '@traefik-labs/faency'
|
||||
import { Fragment, ReactNode, useMemo } from 'react'
|
||||
|
||||
import ScrollableCard from 'components/ScrollableCard'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Card, Flex, Grid, Skeleton as FaencySkeleton, Text } from '@traefiklabs/faency'
|
||||
import { Box, Card, Flex, Grid, Skeleton as FaencySkeleton, Text } from '@traefik-labs/faency'
|
||||
|
||||
import ResourceCard from 'components/resources/ResourceCard'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTr, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTr, Flex, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import Status from './Status'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTr, Badge, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTr, Badge, Flex, Text } from '@traefik-labs/faency'
|
||||
|
||||
import Tooltip from 'components/Tooltip'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, CSS, Flex, Text } from '@traefiklabs/faency'
|
||||
import { Card, CSS, Flex, Text } from '@traefik-labs/faency'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
type ResourceCardProps = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, Flex, Skeleton } from '@traefiklabs/faency'
|
||||
import { Card, Flex, Skeleton } from '@traefik-labs/faency'
|
||||
import { FiAlertTriangle } from 'react-icons/fi'
|
||||
|
||||
import { SectionTitle } from './DetailsCard'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, styled, Text } from '@traefiklabs/faency'
|
||||
import { Box, Flex, styled, Text } from '@traefik-labs/faency'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
import { colorByStatus, iconByStatus } from 'components/resources/Status'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, CSS } from '@traefiklabs/faency'
|
||||
import { Box, CSS } from '@traefik-labs/faency'
|
||||
import { ReactNode } from 'react'
|
||||
import { FiAlertCircle, FiAlertTriangle, FiCheckCircle, FiLoader } from 'react-icons/fi'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Card, Flex, H3, Skeleton, styled, Text } from '@traefiklabs/faency'
|
||||
import { Box, Card, Flex, H3, Skeleton, styled, Text } from '@traefik-labs/faency'
|
||||
import { Chart as ChartJs, ArcElement, Tooltip } from 'chart.js'
|
||||
import { ReactNode, useEffect, useMemo, useState } from 'react'
|
||||
import { Doughnut } from 'react-chartjs-2'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { orderBy } from 'lodash'
|
||||
import { useContext, useEffect, useMemo } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, H1, Skeleton, Text } from '@traefiklabs/faency'
|
||||
import { Flex, H1, Skeleton, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { DetailsCardSkeleton } from 'components/resources/DetailsCard'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, Flex, styled, Link, Tooltip, Box, Text, Skeleton } from '@traefiklabs/faency'
|
||||
import { Card, Flex, styled, Link, Tooltip, Box, Text, Skeleton } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import { FiArrowRight, FiGlobe, FiLayers, FiLogIn, FiZap } from 'react-icons/fi'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Badge, Box, Card, Flex } from '@traefiklabs/faency'
|
||||
import { Badge, Box, Card, Flex } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import TlsIcon from './TlsIcon'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Text } from '@traefiklabs/faency'
|
||||
import { Flex, Text } from '@traefik-labs/faency'
|
||||
import { FiGlobe } from 'react-icons/fi'
|
||||
|
||||
import { getProviderFromName } from './Servers'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Text } from '@traefiklabs/faency'
|
||||
import { Flex, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import { FiGlobe } from 'react-icons/fi'
|
||||
|
||||
@@ -16,29 +16,18 @@ type ServersProps = {
|
||||
type Server = {
|
||||
url?: string
|
||||
address?: string
|
||||
weight?: number
|
||||
}
|
||||
|
||||
type ServerStatus = {
|
||||
[server: string]: string
|
||||
}
|
||||
|
||||
function getServerStatusList(data: Service.Details): ServerStatus {
|
||||
const serversList: ServerStatus = {}
|
||||
|
||||
data.loadBalancer?.servers?.forEach((server: Server) => {
|
||||
const serverKey = server.address || server.url
|
||||
if (serverKey) {
|
||||
serversList[serverKey] = 'DOWN'
|
||||
}
|
||||
})
|
||||
|
||||
if (data.serverStatus) {
|
||||
Object.entries(data.serverStatus).forEach(([server, status]) => {
|
||||
serversList[server] = status
|
||||
})
|
||||
function getServerStatusList(data: Service.Details) {
|
||||
if (!data?.loadBalancer?.servers) {
|
||||
return []
|
||||
}
|
||||
|
||||
return serversList
|
||||
return data.loadBalancer?.servers?.map((server: Server) => ({
|
||||
url: server.address || server.url,
|
||||
status: data.serverStatus?.[server.address || server.url || '-'] || 'DOWN',
|
||||
weight: server.weight ?? 1,
|
||||
}))
|
||||
}
|
||||
|
||||
export const getProviderFromName = (serviceName: string, defaultProvider: string): string => {
|
||||
@@ -47,7 +36,7 @@ export const getProviderFromName = (serviceName: string, defaultProvider: string
|
||||
}
|
||||
|
||||
const Servers = ({ data, protocol }: ServersProps) => {
|
||||
const serversList = getServerStatusList(data)
|
||||
const serversList = useMemo(() => getServerStatusList(data), [data])
|
||||
|
||||
const isTcp = useMemo(() => protocol === 'tcp', [protocol])
|
||||
const isUdp = useMemo(() => protocol === 'udp', [protocol])
|
||||
@@ -57,35 +46,39 @@ const Servers = ({ data, protocol }: ServersProps) => {
|
||||
return (
|
||||
<Flex direction="column" gap={2}>
|
||||
<SectionTitle icon={<FiGlobe size={20} />} title="Servers" />
|
||||
<PaginatedTable
|
||||
data={Object.entries(serversList).map(([server, status]) => ({
|
||||
server,
|
||||
status,
|
||||
}))}
|
||||
columns={[
|
||||
...(isUdp ? [] : [{ key: 'status' as const, header: 'Status' }]),
|
||||
{ key: 'server' as const, header: isTcp ? 'Address' : 'URL' },
|
||||
]}
|
||||
testId="servers-list"
|
||||
renderCell={(key, value) => {
|
||||
if (key === 'status') {
|
||||
return (
|
||||
<Flex align="center" gap={2}>
|
||||
<ResourceStatus status={value === 'UP' ? 'enabled' : 'disabled'} />
|
||||
<Text css={{ color: value === 'UP' ? colorByStatus.success : colorByStatus.disabled }}>{value}</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
if (key === 'server') {
|
||||
return (
|
||||
<Tooltip label={value} action="copy">
|
||||
<Text>{value}</Text>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return <Text>{value}</Text>
|
||||
}}
|
||||
/>
|
||||
{serversList?.length > 0 && (
|
||||
<PaginatedTable
|
||||
data={serversList?.map(({ url, status, weight }) => ({
|
||||
server: url,
|
||||
status,
|
||||
weight,
|
||||
}))}
|
||||
columns={[
|
||||
...(isUdp ? [] : [{ key: 'status' as const, header: 'Status' }]),
|
||||
{ key: 'server' as const, header: isTcp ? 'Address' : 'URL' },
|
||||
...(isUdp ? [] : [{ key: 'weight' as const, header: 'Weight' }]),
|
||||
]}
|
||||
testId={`${protocol}-servers-list`}
|
||||
renderCell={(key, value) => {
|
||||
if (key === 'status') {
|
||||
return (
|
||||
<Flex align="center" gap={2}>
|
||||
<ResourceStatus status={value === 'UP' ? 'enabled' : 'disabled'} />
|
||||
<Text css={{ color: value === 'UP' ? colorByStatus.success : colorByStatus.disabled }}>{value}</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
if (key === 'server') {
|
||||
return (
|
||||
<Tooltip label={value as string} action="copy">
|
||||
<Text>{value}</Text>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return <Text>{value}</Text>
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Badge } from '@traefiklabs/faency'
|
||||
import { Badge } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import ProviderIcon from 'components/icons/providers'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, H1, Skeleton, Text } from '@traefiklabs/faency'
|
||||
import { Box, Flex, H1, Skeleton, Text } from '@traefik-labs/faency'
|
||||
|
||||
import MirrorServices from './MirrorServices'
|
||||
import Servers from './Servers'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { FiGlobe } from 'react-icons/fi'
|
||||
|
||||
import { getProviderFromName } from './utils'
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
VariantProps,
|
||||
AriaThead,
|
||||
AriaTh,
|
||||
} from '@traefiklabs/faency'
|
||||
} from '@traefik-labs/faency'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
type AriaTableSkeletonProps = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTr, VariantProps, styled } from '@traefiklabs/faency'
|
||||
import { AriaTr, VariantProps, styled } from '@traefik-labs/faency'
|
||||
import { ComponentProps, forwardRef, ReactNode } from 'react'
|
||||
|
||||
import { useHrefWithReturnTo } from 'hooks/use-href-with-return-to'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaThead, AriaTr, Box, Button, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaThead, AriaTr, Box, Button, Flex, Text } from '@traefik-labs/faency'
|
||||
import { ReactNode, useEffect, useRef, useState } from 'react'
|
||||
import { FiChevronLeft, FiChevronRight, FiChevronsLeft, FiChevronsRight } from 'react-icons/fi'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTh, CSS, Flex, Label } from '@traefiklabs/faency'
|
||||
import { AriaTh, CSS, Flex, Label } from '@traefik-labs/faency'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Button, Flex, TextField, InputHandle } from '@traefiklabs/faency'
|
||||
import { Box, Button, Flex, TextField, InputHandle } from '@traefik-labs/faency'
|
||||
import { isUndefined, omitBy } from 'lodash'
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { FiSearch, FiXCircle } from 'react-icons/fi'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTd, AriaTr } from '@traefiklabs/faency'
|
||||
import { AriaTd, AriaTr } from '@traefik-labs/faency'
|
||||
import { stringify } from 'query-string'
|
||||
import { ReactNode } from 'react'
|
||||
import useSWRInfinite, { SWRInfiniteConfiguration } from 'swr/infinite'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, styled } from '@traefiklabs/faency'
|
||||
import { Flex, styled } from '@traefik-labs/faency'
|
||||
|
||||
import breakpoints from 'utils/breakpoints'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTd, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTd, Flex, Text } from '@traefik-labs/faency'
|
||||
import { FiAlertTriangle } from 'react-icons/fi'
|
||||
|
||||
type EmptyPlaceholderProps = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Button, Text } from '@traefiklabs/faency'
|
||||
import { Box, Button, Text } from '@traefik-labs/faency'
|
||||
import { FallbackProps } from 'react-error-boundary'
|
||||
|
||||
const ErrorFallback = ({ error, resetErrorBoundary }: FallbackProps) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, globalCss, styled } from '@traefiklabs/faency'
|
||||
import { Flex, globalCss, styled } from '@traefik-labs/faency'
|
||||
import { ReactNode, useMemo, useState } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
Text,
|
||||
Tooltip,
|
||||
VisuallyHidden,
|
||||
} from '@traefiklabs/faency'
|
||||
} from '@traefik-labs/faency'
|
||||
import { useContext, useEffect, useMemo, useState } from 'react'
|
||||
import { BsChevronDoubleRight, BsChevronDoubleLeft } from 'react-icons/bs'
|
||||
import { matchPath, useHref } from 'react-router'
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
Link,
|
||||
Text,
|
||||
Tooltip,
|
||||
} from '@traefiklabs/faency'
|
||||
} from '@traefik-labs/faency'
|
||||
import { useContext, useMemo } from 'react'
|
||||
import { Helmet } from 'react-helmet-async'
|
||||
import { FiBookOpen, FiChevronLeft, FiGithub, FiHeart, FiHelpCircle } from 'react-icons/fi'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Button, Flex, H1, Text } from '@traefiklabs/faency'
|
||||
import { Box, Button, Flex, H1, Text } from '@traefik-labs/faency'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
import PageTitle from 'layout/PageTitle'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Card, CSS, Flex, Grid, H2, Text } from '@traefiklabs/faency'
|
||||
import { Card, CSS, Flex, Grid, H2, Text } from '@traefik-labs/faency'
|
||||
import { ReactNode, useMemo } from 'react'
|
||||
import useSWR from 'swr'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Box, Flex } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Box, Flex } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -89,9 +89,10 @@ describe('<HttpServicePage />', () => {
|
||||
expect(serviceDetails.innerHTML).toContain('Pass host header')
|
||||
expect(serviceDetails.innerHTML).toContain('True')
|
||||
|
||||
const serversList = getByTestId('servers-list')
|
||||
const serversList = getByTestId('http-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(1)
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.12:80')
|
||||
expect(serversList.innerHTML).toContain('1')
|
||||
|
||||
const routersTable = getByTestId('routers-table')
|
||||
expect(routersTable.querySelectorAll('a[role="row"]')).toHaveLength(2)
|
||||
@@ -107,6 +108,47 @@ describe('<HttpServicePage />', () => {
|
||||
}).toThrow('Unable to find an element by: [data-testid="mirror-services"]')
|
||||
})
|
||||
|
||||
it('should render a service with server weights', async () => {
|
||||
const mockData = {
|
||||
loadBalancer: {
|
||||
servers: [
|
||||
{
|
||||
url: 'http://10.0.1.12:80',
|
||||
weight: 3,
|
||||
},
|
||||
{
|
||||
url: 'http://10.0.1.13:80',
|
||||
weight: 5,
|
||||
},
|
||||
],
|
||||
passHostHeader: true,
|
||||
},
|
||||
status: 'enabled',
|
||||
usedBy: [],
|
||||
serverStatus: {
|
||||
'http://10.0.1.12:80': 'UP',
|
||||
'http://10.0.1.13:80': 'UP',
|
||||
},
|
||||
name: 'service-weighted',
|
||||
provider: 'docker',
|
||||
type: 'loadbalancer',
|
||||
routers: [],
|
||||
}
|
||||
|
||||
const { getByTestId } = renderWithProviders(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
<ServiceDetail name="mock-service" data={mockData as any} error={undefined} protocol="http" />,
|
||||
{ route: '/http/services/mock-service', withPage: true },
|
||||
)
|
||||
|
||||
const serversList = getByTestId('http-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(2)
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.12:80')
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.13:80')
|
||||
expect(serversList.innerHTML).toContain('3')
|
||||
expect(serversList.innerHTML).toContain('5')
|
||||
})
|
||||
|
||||
it('should render a service with health check', async () => {
|
||||
const mockData = {
|
||||
loadBalancer: {
|
||||
@@ -217,7 +259,7 @@ describe('<HttpServicePage />', () => {
|
||||
}).toThrow('Unable to find an element by: [data-testid="health-check"]')
|
||||
|
||||
expect(() => {
|
||||
getByTestId('servers-list')
|
||||
}).toThrow('Unable to find an element by: [data-testid="servers-list"]')
|
||||
getByTestId('http-servers-list')
|
||||
}).toThrow('Unable to find an element by: [data-testid="http-servers-list"]')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Flex, Image, Link, Text } from '@traefiklabs/faency'
|
||||
import { Box, Flex, Image, Link, Text } from '@traefik-labs/faency'
|
||||
import { useMemo, useEffect, useState } from 'react'
|
||||
import { Helmet } from 'react-helmet-async'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Badge, Box, Flex, Text } from '@traefiklabs/faency'
|
||||
import { Badge, Box, Flex, Text } from '@traefik-labs/faency'
|
||||
import { useContext, useState } from 'react'
|
||||
import { BsChevronRight } from 'react-icons/bs'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { useId } from 'react'
|
||||
|
||||
import { CustomIconProps } from 'components/icons'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
|
||||
import { CustomIconProps } from 'components/icons'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { useId } from 'react'
|
||||
|
||||
import { CustomIconProps } from 'components/icons'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex } from '@traefiklabs/faency'
|
||||
import { Flex } from '@traefik-labs/faency'
|
||||
import { useId } from 'react'
|
||||
|
||||
import { CustomIconProps } from 'components/icons'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Box, Flex } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Box, Flex } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -101,9 +101,10 @@ describe('<TcpServicePage />', () => {
|
||||
expect(healthCheck.innerHTML).toContain('Expect')
|
||||
expect(healthCheck.innerHTML).toContain('PONG')
|
||||
|
||||
const serversList = getByTestId('servers-list')
|
||||
const serversList = getByTestId('tcp-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(1)
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.12:80')
|
||||
expect(serversList.innerHTML).toContain('1')
|
||||
|
||||
const routersTable = getByTestId('routers-table')
|
||||
expect(routersTable.querySelectorAll('a[role="row"]')).toHaveLength(1)
|
||||
@@ -113,6 +114,11 @@ describe('<TcpServicePage />', () => {
|
||||
it('should render the service servers from the serverStatus property', async () => {
|
||||
const mockData = {
|
||||
loadBalancer: {
|
||||
servers: [
|
||||
{
|
||||
address: 'http://10.0.1.12:81',
|
||||
},
|
||||
],
|
||||
terminationDelay: 10,
|
||||
},
|
||||
status: 'enabled',
|
||||
@@ -154,7 +160,7 @@ describe('<TcpServicePage />', () => {
|
||||
{ route: '/tcp/services/mock-service', withPage: true },
|
||||
)
|
||||
|
||||
const serversList = getByTestId('servers-list')
|
||||
const serversList = getByTestId('tcp-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(1)
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.12:81')
|
||||
|
||||
@@ -185,6 +191,47 @@ describe('<TcpServicePage />', () => {
|
||||
}).toThrow('Unable to find an element by: [data-testid="routers-table"]')
|
||||
})
|
||||
|
||||
it('should render the service with server weights', async () => {
|
||||
const mockData = {
|
||||
loadBalancer: {
|
||||
servers: [
|
||||
{
|
||||
address: '10.0.1.12:80',
|
||||
weight: 3,
|
||||
},
|
||||
{
|
||||
address: '10.0.1.13:80',
|
||||
weight: 7,
|
||||
},
|
||||
],
|
||||
terminationDelay: 10,
|
||||
},
|
||||
serverStatus: {
|
||||
'10.0.1.12:80': 'UP',
|
||||
'10.0.1.13:80': 'UP',
|
||||
},
|
||||
status: 'enabled',
|
||||
usedBy: [],
|
||||
name: 'service-weighted-servers',
|
||||
provider: 'docker',
|
||||
type: 'loadbalancer',
|
||||
routers: [],
|
||||
}
|
||||
|
||||
const { getByTestId } = renderWithProviders(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
<ServiceDetail name="mock-service" data={mockData as any} error={undefined} protocol="tcp" />,
|
||||
{ route: '/tcp/services/mock-service', withPage: true },
|
||||
)
|
||||
|
||||
const serversList = getByTestId('tcp-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(2)
|
||||
expect(serversList.innerHTML).toContain('10.0.1.12:80')
|
||||
expect(serversList.innerHTML).toContain('10.0.1.13:80')
|
||||
expect(serversList.innerHTML).toContain('3')
|
||||
expect(serversList.innerHTML).toContain('7')
|
||||
})
|
||||
|
||||
it('should render weighted services', async () => {
|
||||
const mockData = {
|
||||
weighted: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -79,7 +79,7 @@ describe('<UdpServicePage />', () => {
|
||||
expect(serviceDetails.innerHTML).toContain('Termination delay')
|
||||
expect(serviceDetails.innerHTML).toContain('10 ms')
|
||||
|
||||
const serversList = getByTestId('servers-list')
|
||||
const serversList = getByTestId('udp-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(1)
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.12:80')
|
||||
|
||||
@@ -91,6 +91,11 @@ describe('<UdpServicePage />', () => {
|
||||
it('should render the service servers from the serverStatus property', async () => {
|
||||
const mockData = {
|
||||
loadBalancer: {
|
||||
servers: [
|
||||
{
|
||||
address: 'http://10.0.1.12:81',
|
||||
},
|
||||
],
|
||||
terminationDelay: 10,
|
||||
},
|
||||
status: 'enabled',
|
||||
@@ -132,7 +137,7 @@ describe('<UdpServicePage />', () => {
|
||||
{ route: '/udp/services/mock-service', withPage: true },
|
||||
)
|
||||
|
||||
const serversList = getByTestId('servers-list')
|
||||
const serversList = getByTestId('udp-servers-list')
|
||||
expect(serversList.childNodes.length).toBe(1)
|
||||
expect(serversList.innerHTML).toContain('http://10.0.1.12:81')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex, Text } from '@traefiklabs/faency'
|
||||
import { AriaTable, AriaTbody, AriaTd, AriaTfoot, AriaThead, AriaTr, Flex, Text } from '@traefik-labs/faency'
|
||||
import { useMemo } from 'react'
|
||||
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cleanup, render } from '@testing-library/react'
|
||||
import { FaencyProvider } from '@traefiklabs/faency'
|
||||
import { FaencyProvider } from '@traefik-labs/faency'
|
||||
import { HelmetProvider } from 'react-helmet-async'
|
||||
import { MemoryRouter } from 'react-router-dom'
|
||||
import { SWRConfig } from 'swr'
|
||||
|
||||
+404
-534
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user