fix(dns-hole-summary): calculation for domains and percentage for multiple integrations (#1894)
This commit is contained in:
@@ -1091,7 +1091,8 @@
|
|||||||
"adsBlockedTodayPercentage": "Blocked today",
|
"adsBlockedTodayPercentage": "Blocked today",
|
||||||
"dnsQueriesToday": "Queries today",
|
"dnsQueriesToday": "Queries today",
|
||||||
"domainsBeingBlocked": "Domains on blocklist"
|
"domainsBeingBlocked": "Domains on blocklist"
|
||||||
}
|
},
|
||||||
|
"domainsTooltip": "Due to multiple integrations Homarr can't calculate the exact number of domains being blocked"
|
||||||
},
|
},
|
||||||
"dnsHoleControls": {
|
"dnsHoleControls": {
|
||||||
"name": "DNS Hole Controls",
|
"name": "DNS Hole Controls",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import type { BoxProps } from "@mantine/core";
|
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 { useElementSize } from "@mantine/hooks";
|
||||||
import { IconBarrierBlock, IconPercentage, IconSearch, IconWorldWww } from "@tabler/icons-react";
|
import { IconBarrierBlock, IconPercentage, IconSearch, IconWorldWww } from "@tabler/icons-react";
|
||||||
|
|
||||||
@@ -98,11 +98,11 @@ const stats = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: IconPercentage,
|
icon: IconPercentage,
|
||||||
value: (data) =>
|
value: (data) => {
|
||||||
`${formatNumber(
|
const totalCount = data.reduce((count, { dnsQueriesToday }) => count + dnsQueriesToday, 0);
|
||||||
data.reduce((count, { adsBlockedTodayPercentage }) => count + adsBlockedTodayPercentage, 0),
|
const blocked = data.reduce((count, { adsBlockedToday }) => count + adsBlockedToday, 0);
|
||||||
2,
|
return `${formatNumber(totalCount === 0 ? 0 : (blocked / totalCount) * 100, 2)}%`;
|
||||||
)}%`,
|
},
|
||||||
label: (t) => t("widget.dnsHoleSummary.data.adsBlockedTodayPercentage"),
|
label: (t) => t("widget.dnsHoleSummary.data.adsBlockedTodayPercentage"),
|
||||||
color: "rgba(255, 165, 20, 0.4)", // YELLOW
|
color: "rgba(255, 165, 20, 0.4)", // YELLOW
|
||||||
},
|
},
|
||||||
@@ -118,11 +118,17 @@ const stats = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: IconWorldWww,
|
icon: IconWorldWww,
|
||||||
value: (data) =>
|
value: (data) => {
|
||||||
formatNumber(
|
// We use a suffix to indicate that there might be more domains in the at least two lists.
|
||||||
data.reduce((count, { domainsBeingBlocked }) => count + domainsBeingBlocked, 0),
|
const suffix = data.length >= 2 ? "+" : "";
|
||||||
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"),
|
label: (t) => t("widget.dnsHoleSummary.data.domainsBeingBlocked"),
|
||||||
color: "rgba(0, 176, 96, 0.4)", // GREEN
|
color: "rgba(0, 176, 96, 0.4)", // GREEN
|
||||||
},
|
},
|
||||||
@@ -130,7 +136,8 @@ const stats = [
|
|||||||
|
|
||||||
interface StatItem {
|
interface StatItem {
|
||||||
icon: TablerIcon;
|
icon: TablerIcon;
|
||||||
value: (x: DnsHoleSummary[]) => string;
|
value: (summaries: DnsHoleSummary[]) => string;
|
||||||
|
tooltip?: (summaries: DnsHoleSummary[], t: TranslationFunction) => string | undefined;
|
||||||
label: stringOrTranslation;
|
label: stringOrTranslation;
|
||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
@@ -144,58 +151,61 @@ interface StatCardProps {
|
|||||||
const StatCard = ({ item, data, usePiHoleColors, t }: StatCardProps) => {
|
const StatCard = ({ item, data, usePiHoleColors, t }: StatCardProps) => {
|
||||||
const { ref, height, width } = useElementSize();
|
const { ref, height, width } = useElementSize();
|
||||||
const isLong = width > height + 20;
|
const isLong = width > height + 20;
|
||||||
|
const tooltip = item.tooltip?.(data, t);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<TooltipFloating label={tooltip} disabled={!tooltip} w={250} multiline>
|
||||||
ref={ref}
|
<Card
|
||||||
className="summary-card"
|
ref={ref}
|
||||||
m="2cqmin"
|
className="summary-card"
|
||||||
p="2.5cqmin"
|
m="2cqmin"
|
||||||
bg={usePiHoleColors ? item.color : "rgba(96, 96, 96, 0.1)"}
|
p="2.5cqmin"
|
||||||
style={{
|
bg={usePiHoleColors ? item.color : "rgba(96, 96, 96, 0.1)"}
|
||||||
flex: 1,
|
style={{
|
||||||
}}
|
flex: 1,
|
||||||
withBorder
|
}}
|
||||||
>
|
withBorder
|
||||||
<Flex
|
|
||||||
className="summary-card-elements"
|
|
||||||
h="100%"
|
|
||||||
w="100%"
|
|
||||||
align="center"
|
|
||||||
justify="space-evenly"
|
|
||||||
direction={isLong ? "row" : "column"}
|
|
||||||
style={{ containerType: "size" }}
|
|
||||||
>
|
>
|
||||||
<item.icon className="summary-card-icon" size="40cqmin" style={{ margin: "2.5cqmin" }} />
|
|
||||||
<Flex
|
<Flex
|
||||||
className="summary-card-texts"
|
className="summary-card-elements"
|
||||||
justify="center"
|
|
||||||
direction="column"
|
|
||||||
style={{
|
|
||||||
flex: isLong ? 1 : undefined,
|
|
||||||
}}
|
|
||||||
w="100%"
|
|
||||||
h="100%"
|
h="100%"
|
||||||
gap="1cqmin"
|
w="100%"
|
||||||
|
align="center"
|
||||||
|
justify="space-evenly"
|
||||||
|
direction={isLong ? "row" : "column"}
|
||||||
|
style={{ containerType: "size" }}
|
||||||
>
|
>
|
||||||
<Text
|
<item.icon className="summary-card-icon" size="40cqmin" style={{ margin: "2.5cqmin" }} />
|
||||||
key={item.value(data)}
|
<Flex
|
||||||
className="summary-card-value text-flash"
|
className="summary-card-texts"
|
||||||
ta="center"
|
justify="center"
|
||||||
size="20cqmin"
|
direction="column"
|
||||||
fw="bold"
|
style={{
|
||||||
style={{ "--glow-size": "2.5cqmin" }}
|
flex: isLong ? 1 : undefined,
|
||||||
|
}}
|
||||||
|
w="100%"
|
||||||
|
h="100%"
|
||||||
|
gap="1cqmin"
|
||||||
>
|
>
|
||||||
{item.value(data)}
|
<Text
|
||||||
</Text>
|
key={item.value(data)}
|
||||||
{item.label && (
|
className="summary-card-value text-flash"
|
||||||
<Text className="summary-card-label" ta="center" size="15cqmin">
|
ta="center"
|
||||||
{translateIfNecessary(t, item.label)}
|
size="20cqmin"
|
||||||
|
fw="bold"
|
||||||
|
style={{ "--glow-size": "2.5cqmin" }}
|
||||||
|
>
|
||||||
|
{item.value(data)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
{item.label && (
|
||||||
|
<Text className="summary-card-label" ta="center" size="15cqmin">
|
||||||
|
{translateIfNecessary(t, item.label)}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Card>
|
||||||
</Card>
|
</TooltipFloating>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user