fix: DnsHole controls timer (#953)

* fix: DnsHole controls timer

* fix: use plural naming

* fix: reviewed changes

* fix: change ControlsCard to jsx component

* fix: DeepSource
This commit is contained in:
Yossi Hillali
2024-08-28 11:26:36 +03:00
committed by GitHub
parent 3771a61c49
commit 69e69ee315
3 changed files with 73 additions and 29 deletions

View File

@@ -123,7 +123,7 @@ export class AdGuardHomeIntegration extends Integration implements DnsHoleSummar
}
}
public async disableAsync(duration?: number): Promise<void> {
public async disableAsync(duration = 0): Promise<void> {
const response = await fetch(`${this.integration.url}/control/protection`, {
method: "POST",
headers: {
@@ -132,7 +132,7 @@ export class AdGuardHomeIntegration extends Integration implements DnsHoleSummar
},
body: JSON.stringify({
enabled: false,
duration: duration,
duration: duration * 1000,
}),
});
if (!response.ok) {

View File

@@ -8,11 +8,11 @@ import { useI18n } from "@homarr/translation/client";
interface TimerModalProps {
opened: boolean;
close: () => void;
integrationIds: string[];
selectedIntegrationIds: string[];
disableDns: (data: { duration: number; integrationId: string }) => void;
}
const TimerModal = ({ opened, close, integrationIds, disableDns }: TimerModalProps) => {
const TimerModal = ({ opened, close, selectedIntegrationIds, disableDns }: TimerModalProps) => {
const t = useI18n();
const [hours, setHours] = useState(0);
const [minutes, setMinutes] = useState(0);
@@ -21,7 +21,7 @@ const TimerModal = ({ opened, close, integrationIds, disableDns }: TimerModalPro
const handleSetTimer = () => {
const duration = hours * 3600 + minutes * 60;
integrationIds.forEach((integrationId) => {
selectedIntegrationIds.forEach((integrationId) => {
disableDns({ duration, integrationId });
});
setHours(0);

View File

@@ -24,6 +24,7 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
const [status, setStatus] = useState<{ integrationId: string; enabled: boolean }[]>(
integrationIds.map((id) => ({ integrationId: id, enabled: false })),
);
const [selectedIntegrationIds, setSelectedIntegrationIds] = useState<string[]>([]);
const [opened, { close, open }] = useDisclosure(false);
const [data] = clientApi.widget.dnsHole.summary.useSuspenseQuery(
@@ -67,8 +68,10 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
}
};
const allEnabled = status.every((item) => item.enabled);
const allDisabled = status.every((item) => !item.enabled);
const enabledIntegrations = integrationIds.filter((id) => status.find((item) => item.integrationId === id)?.enabled);
const disabledIntegrations = integrationIds.filter(
(id) => !status.find((item) => item.integrationId === id)?.enabled,
);
return (
<Flex h="100%" direction="column" gap={0} p="2.5cqmin">
@@ -76,10 +79,8 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
<Flex gap="2.5cqmin">
<Tooltip label={t("widget.dnsHoleControls.controls.enableAll")}>
<Button
onClick={() => {
integrationIds.forEach((integrationId) => enableDns({ integrationId }));
}}
disabled={allEnabled}
onClick={() => disabledIntegrations.forEach((integrationId) => enableDns({ integrationId }))}
disabled={disabledIntegrations.length === 0}
variant="light"
color="green"
fullWidth
@@ -90,17 +91,25 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
</Tooltip>
<Tooltip label={t("widget.dnsHoleControls.controls.setTimer")}>
<Button onClick={open} disabled={allDisabled} variant="light" color="yellow" fullWidth h="2rem">
<Button
onClick={() => {
setSelectedIntegrationIds(enabledIntegrations);
open();
}}
disabled={enabledIntegrations.length === 0}
variant="light"
color="yellow"
fullWidth
h="2rem"
>
<IconClockPause size={20} />
</Button>
</Tooltip>
<Tooltip label={t("widget.dnsHoleControls.controls.disableAll")}>
<Button
onClick={() => {
integrationIds.forEach((integrationId) => disableDns({ integrationId, duration: 0 }));
}}
disabled={allDisabled}
onClick={() => enabledIntegrations.forEach((integrationId) => disableDns({ integrationId, duration: 0 }))}
disabled={enabledIntegrations.length === 0}
variant="light"
color="red"
fullWidth
@@ -113,24 +122,49 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
)}
<Stack gap="2.5cqmin" flex={1} justify={options.showToggleAllButtons ? "flex-end" : "space-evenly"}>
{data.map((integrationData) =>
ControlsCard(integrationData.integrationId, integrationData.integrationKind, toggleDns, status, open, t),
)}
{data.map((integrationData) => (
<ControlsCard
key={integrationData.integrationId}
integrationId={integrationData.integrationId}
integrationKind={integrationData.integrationKind}
toggleDns={toggleDns}
status={status}
setSelectedIntegrationIds={setSelectedIntegrationIds}
open={open}
t={t}
/>
))}
</Stack>
<TimerModal opened={opened} close={close} integrationIds={integrationIds} disableDns={disableDns} />
<TimerModal
opened={opened}
close={close}
selectedIntegrationIds={selectedIntegrationIds}
disableDns={disableDns}
/>
</Flex>
);
}
const ControlsCard = (
integrationId: string,
integrationKind: string,
toggleDns: (integrationId: string) => void,
status: { integrationId: string; enabled: boolean }[],
open: () => void,
t: TranslationFunction,
) => {
interface ControlsCardProps {
integrationId: string;
integrationKind: string;
toggleDns: (integrationId: string) => void;
status: { integrationId: string; enabled: boolean }[];
setSelectedIntegrationIds: (integrationId: string[]) => void;
open: () => void;
t: TranslationFunction;
}
const ControlsCard: React.FC<ControlsCardProps> = ({
integrationId,
integrationKind,
toggleDns,
status,
setSelectedIntegrationIds,
open,
t,
}) => {
const integrationStatus = status.find((item) => item.integrationId === integrationId);
const isEnabled = integrationStatus?.enabled ?? false;
const integrationDef = integrationKind === "piHole" ? integrationDefs.piHole : integrationDefs.adGuardHome;
@@ -149,7 +183,17 @@ const ControlsCard = (
{t(`widget.dnsHoleControls.controls.${isEnabled ? "enabled" : "disabled"}`)}
</Badge>
</UnstyledButton>
<ActionIcon disabled={!isEnabled} size={20} radius="xl" top="2.67px" variant="default" onClick={open}>
<ActionIcon
disabled={!isEnabled}
size={20}
radius="xl"
top="2.67px"
variant="default"
onClick={() => {
setSelectedIntegrationIds([integrationId]);
open();
}}
>
<IconClockPause size={20} color="red" />
</ActionIcon>
</Flex>