From 546c824888a2a6909b831b69ce1a4e283099bda5 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Fri, 10 Jan 2025 14:46:21 +0100 Subject: [PATCH] fix(dns-hole-summary): calculation for domains and percentage for multiple integrations (#1894) --- packages/translation/src/lang/en.json | 3 +- .../src/dns-hole/summary/component.tsx | 120 ++++++++++-------- 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json index 169df14d1..8072ad1ee 100644 --- a/packages/translation/src/lang/en.json +++ b/packages/translation/src/lang/en.json @@ -1091,7 +1091,8 @@ "adsBlockedTodayPercentage": "Blocked today", "dnsQueriesToday": "Queries today", "domainsBeingBlocked": "Domains on blocklist" - } + }, + "domainsTooltip": "Due to multiple integrations Homarr can't calculate the exact number of domains being blocked" }, "dnsHoleControls": { "name": "DNS Hole Controls", diff --git a/packages/widgets/src/dns-hole/summary/component.tsx b/packages/widgets/src/dns-hole/summary/component.tsx index ff4634dff..50d06de42 100644 --- a/packages/widgets/src/dns-hole/summary/component.tsx +++ b/packages/widgets/src/dns-hole/summary/component.tsx @@ -2,7 +2,7 @@ import { useMemo } from "react"; import type { BoxProps } from "@mantine/core"; -import { Avatar, AvatarGroup, Box, Card, Flex, Stack, Text, Tooltip } from "@mantine/core"; +import { Avatar, AvatarGroup, Box, Card, Flex, Stack, Text, Tooltip, TooltipFloating } from "@mantine/core"; import { useElementSize } from "@mantine/hooks"; import { IconBarrierBlock, IconPercentage, IconSearch, IconWorldWww } from "@tabler/icons-react"; @@ -98,11 +98,11 @@ const stats = [ }, { icon: IconPercentage, - value: (data) => - `${formatNumber( - data.reduce((count, { adsBlockedTodayPercentage }) => count + adsBlockedTodayPercentage, 0), - 2, - )}%`, + value: (data) => { + const totalCount = data.reduce((count, { dnsQueriesToday }) => count + dnsQueriesToday, 0); + const blocked = data.reduce((count, { adsBlockedToday }) => count + adsBlockedToday, 0); + return `${formatNumber(totalCount === 0 ? 0 : (blocked / totalCount) * 100, 2)}%`; + }, label: (t) => t("widget.dnsHoleSummary.data.adsBlockedTodayPercentage"), color: "rgba(255, 165, 20, 0.4)", // YELLOW }, @@ -118,11 +118,17 @@ const stats = [ }, { icon: IconWorldWww, - value: (data) => - formatNumber( - data.reduce((count, { domainsBeingBlocked }) => count + domainsBeingBlocked, 0), - 2, - ), + value: (data) => { + // We use a suffix to indicate that there might be more domains in the at least two lists. + const suffix = data.length >= 2 ? "+" : ""; + return ( + formatNumber( + data.reduce((count, { domainsBeingBlocked }) => count + domainsBeingBlocked, 0), + 2, + ) + suffix + ); + }, + tooltip: (data, t) => (data.length >= 2 ? t("widget.dnsHoleSummary.domainsTooltip") : undefined), label: (t) => t("widget.dnsHoleSummary.data.domainsBeingBlocked"), color: "rgba(0, 176, 96, 0.4)", // GREEN }, @@ -130,7 +136,8 @@ const stats = [ interface StatItem { icon: TablerIcon; - value: (x: DnsHoleSummary[]) => string; + value: (summaries: DnsHoleSummary[]) => string; + tooltip?: (summaries: DnsHoleSummary[], t: TranslationFunction) => string | undefined; label: stringOrTranslation; color: string; } @@ -144,58 +151,61 @@ interface StatCardProps { const StatCard = ({ item, data, usePiHoleColors, t }: StatCardProps) => { const { ref, height, width } = useElementSize(); const isLong = width > height + 20; + const tooltip = item.tooltip?.(data, t); return ( - - + - - + - {item.value(data)} - - {item.label && ( - - {translateIfNecessary(t, item.label)} + + {item.value(data)} - )} + {item.label && ( + + {translateIfNecessary(t, item.label)} + + )} + - - + + ); };