import { ActionIcon, Badge, Box, Button, Card, Center, Flex, Group, Image, Stack, Text, Title, Tooltip, UnstyledButton, } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { IconClockPause, IconDeviceGamepad, IconPlayerPlay, IconPlayerStop, } from '@tabler/icons-react'; import { useSession } from 'next-auth/react'; import { useTranslation } from 'next-i18next'; import { useState } from 'react'; import { useConfigContext } from '~/config/provider'; import { api } from '~/utils/api'; import { defineWidget } from '../helper'; import { WidgetLoading } from '../loading'; import { IWidget } from '../widgets'; import { useDnsHoleSummeryQuery } from './DnsHoleSummary'; import { TimerModal } from './TimerModal'; const definition = defineWidget({ id: 'dns-hole-controls', icon: IconDeviceGamepad, options: { showToggleAllButtons: { type: 'switch', defaultValue: true, }, }, gridstack: { minWidth: 2, minHeight: 1, maxWidth: 12, maxHeight: 12, }, component: DnsHoleControlsWidgetTile, }); export type IDnsHoleControlsWidget = IWidget<(typeof definition)['id'], typeof definition>; interface DnsHoleControlsWidgetProps { widget: IDnsHoleControlsWidget; } /** * * @param fetching - a expression that return a boolean if the data is been fetched * @param currentStatus the current status of the dns integration, either enabled or disabled * @returns */ const dnsLightStatus = ( fetching: boolean, currentStatus: 'enabled' | 'disabled' ): 'blue' | 'green' | 'red' => { if (fetching) { return 'blue'; } if (currentStatus === 'enabled') { return 'green'; } return 'red'; }; function DnsHoleControlsWidgetTile({ widget }: DnsHoleControlsWidgetProps) { const { data: sessionData } = useSession(); const [opened, { close, open }] = useDisclosure(false); const [appId, setAppId] = useState(''); const { isInitialLoading, data, isFetching: fetchingDnsSummary } = useDnsHoleSummeryQuery(); const { mutateAsync, isLoading: changingStatus } = useDnsHoleControlMutation(); const { t } = useTranslation(['common', 'modules/dns-hole-controls']); const enableControls = sessionData?.user.isAdmin ?? false; const { name: configName, config } = useConfigContext(); const trpcUtils = api.useUtils(); if (isInitialLoading || !data || !configName) { return ; } if (data.status.length === 0) { return (
{t('modules/dns-hole-controls:descriptor.errors.general.title')} {t('modules/dns-hole-controls:descriptor.errors.general.text')}
); } type getDnsStatusAcc = { enabled: string[]; disabled: string[]; }; const getDnsStatus = () => { const dnsList = data?.status.reduce( (acc: getDnsStatusAcc, dns) => { if (dns.status === 'enabled') { acc.enabled.push(dns.appId); } else if (dns.status === 'disabled') { acc.disabled.push(dns.appId); } return acc; }, { enabled: [], disabled: [] } ); if (dnsList.enabled.length === 0 && dnsList.disabled.length === 0) { return undefined; } return dnsList; }; const toggleDns = async ( action: 'enable' | 'disable', appsToChange?: string[], hours: number = 0, minutes: number = 0 ) => { const duration = hours * 3600 + minutes * 60; await mutateAsync( { action, duration, configName, appsToChange, }, { onSettled: () => { trpcUtils.dnsHole.summary.invalidate(); }, } ); setAppId(''); }; return ( {enableControls && widget.properties.showToggleAllButtons && ( )} {data.status.map((dnsHole, index) => { const app = config?.apps.find((x) => x.id === dnsHole.appId); if (!app) { return null; } return ( ({ backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[2], textAlign: 'center', padding: 5, borderRadius: theme.radius.md, })} > {app.name} toggleDns(dnsHole.status === 'enabled' ? 'disable' : 'enable', [app.id]) } disabled={fetchingDnsSummary || changingStatus} style={{ pointerEvents: enableControls ? 'auto' : 'none' }} > ({ root: { '&:hover': { background: theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[2], }, '&:active': { background: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[3], }, }, })} > {t(dnsHole.status)} {enableControls && ( { setAppId(app.id); open(); }} > )} ); })} ); } const useDnsHoleControlMutation = () => api.dnsHole.control.useMutation(); export default definition;