diff --git a/public/locales/en/modules/dns-hole-summary.json b/public/locales/en/modules/dns-hole-summary.json index 207d37e1f..17c1149a6 100644 --- a/public/locales/en/modules/dns-hole-summary.json +++ b/public/locales/en/modules/dns-hole-summary.json @@ -6,6 +6,14 @@ "title": "Settings for DNS Hole summary", "usePiHoleColors": { "label": "Use colors from PiHole" + }, + "layout": { + "label": "Layout", + "data": { + "grid": "2 by 2", + "row": "Horizontal", + "column": "Vertical" + } } } }, diff --git a/src/widgets/dnshole/DnsHoleSummary.tsx b/src/widgets/dnshole/DnsHoleSummary.tsx index bcfc443e5..fd1c9f75a 100644 --- a/src/widgets/dnshole/DnsHoleSummary.tsx +++ b/src/widgets/dnshole/DnsHoleSummary.tsx @@ -1,4 +1,5 @@ -import { Card, Center, Container, Stack, Text } from '@mantine/core'; +import { Card, Center, Container, Flex, Text } from '@mantine/core'; +import { useElementSize } from '@mantine/hooks'; import { IconAd, IconBarrierBlock, @@ -7,6 +8,7 @@ import { IconWorldWww, } from '@tabler/icons-react'; import { useTranslation } from 'next-i18next'; +import React from 'react'; import { useConfigContext } from '~/config/provider'; import { api } from '~/utils/api'; @@ -23,10 +25,15 @@ const definition = defineWidget({ type: 'switch', defaultValue: true, }, + layout: { + type: 'select', + defaultValue: 'grid', + data: [{ value: 'grid' }, { value: 'row' }, { value: 'column' }], + }, }, gridstack: { minWidth: 2, - minHeight: 2, + minHeight: 1, maxWidth: 12, maxHeight: 12, }, @@ -42,6 +49,7 @@ interface DnsHoleSummaryWidgetProps { function DnsHoleSummaryWidgetTile({ widget }: DnsHoleSummaryWidgetProps) { const { t } = useTranslation('modules/dns-hole-summary'); const { isInitialLoading, data } = useDnsHoleSummeryQuery(); + const flexLayout = widget.properties.layout as 'row' | 'column'; if (isInitialLoading || !data) { return ; @@ -49,134 +57,46 @@ function DnsHoleSummaryWidgetTile({ widget }: DnsHoleSummaryWidgetProps) { return ( - { - if (!widget.properties.usePiHoleColors) { - return {}; - } - - if (theme.colorScheme === 'dark') { - return { - backgroundColor: 'rgba(240, 82, 60, 0.4)', - }; - } - - return { - backgroundColor: 'rgba(240, 82, 60, 0.2)', - }; - }} - withBorder - > -
- - -
- {formatNumber(data.adsBlockedToday, 0)} - - {t('card.metrics.queriesBlockedToday')} - -
-
-
-
- { - if (!widget.properties.usePiHoleColors) { - return {}; - } - - if (theme.colorScheme === 'dark') { - return { - backgroundColor: 'rgba(255, 165, 20, 0.4)', - }; - } - - return { - backgroundColor: 'rgba(255, 165, 20, 0.4)', - }; - }} - withBorder - > -
- - - {(data.adsBlockedTodayPercentage * 100).toFixed(2)}% - -
-
- { - if (!widget.properties.usePiHoleColors) { - return {}; - } - - if (theme.colorScheme === 'dark') { - return { - backgroundColor: 'rgba(0, 175, 218, 0.4)', - }; - } - - return { - backgroundColor: 'rgba(0, 175, 218, 0.4)', - }; - }} - withBorder - > -
- - -
- {formatNumber(data.dnsQueriesToday, 3)} - - {t('card.metrics.queriesToday')} - -
-
-
-
- { - if (!widget.properties.usePiHoleColors) { - return {}; - } - - if (theme.colorScheme === 'dark') { - return { - backgroundColor: 'rgba(0, 176, 96, 0.4)', - }; - } - - return { - backgroundColor: 'rgba(0, 176, 96, 0.4)', - }; - }} - withBorder - > -
- - -
- {formatNumber(data.domainsBeingBlocked, 0)} - - {t('card.metrics.domainsOnAdlist')} - -
-
-
-
+ } + number={formatNumber(data.adsBlockedToday, 2)} + label={t('card.metrics.queriesBlockedToday') as string} + color={ + widget.properties.usePiHoleColors ? 'rgba(240, 82, 60, 0.4)' : 'rgba(96, 96, 96, 0.1)' + } + /> + } + number={(data.adsBlockedTodayPercentage * 100).toFixed(2) + '%'} + color={ + widget.properties.usePiHoleColors ? 'rgba(255, 165, 20, 0.4)' : 'rgba(96, 96, 96, 0.1)' + } + /> + } + number={formatNumber(data.dnsQueriesToday, 2)} + label={t('card.metrics.queriesToday') as string} + color={ + widget.properties.usePiHoleColors ? 'rgba(0, 175, 218, 0.4)' : 'rgba(96, 96, 96, 0.1)' + } + /> + } + number={formatNumber(data.domainsBeingBlocked, 2)} + label={t('card.metrics.domainsOnAdlist') as string} + color={ + widget.properties.usePiHoleColors ? 'rgba(0, 176, 96, 0.4)' : 'rgba(96, 96, 96, 0.1)' + } + />
); } @@ -194,4 +114,59 @@ export const useDnsHoleSummeryQuery = () => { ); }; +interface StatCardProps { + icon: JSX.Element; + number: string; + label?: string; + color?: string; +} + +const StatCard = ({ icon, number, label, color }: StatCardProps) => { + const { ref, height, width } = useElementSize(); + return ( + +
+ height + 20 ? 'row' : 'column'} + > + {React.cloneElement(icon, { + size: 30, + style: { margin: '0 10' } + })} +
+ + {number} + + {label && ( + + {label} + + )} +
+
+
+
+ ); +}; + export default definition;