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:
@@ -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`, {
|
const response = await fetch(`${this.integration.url}/control/protection`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -132,7 +132,7 @@ export class AdGuardHomeIntegration extends Integration implements DnsHoleSummar
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
duration: duration,
|
duration: duration * 1000,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import { useI18n } from "@homarr/translation/client";
|
|||||||
interface TimerModalProps {
|
interface TimerModalProps {
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
integrationIds: string[];
|
selectedIntegrationIds: string[];
|
||||||
disableDns: (data: { duration: number; integrationId: string }) => void;
|
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 t = useI18n();
|
||||||
const [hours, setHours] = useState(0);
|
const [hours, setHours] = useState(0);
|
||||||
const [minutes, setMinutes] = useState(0);
|
const [minutes, setMinutes] = useState(0);
|
||||||
@@ -21,7 +21,7 @@ const TimerModal = ({ opened, close, integrationIds, disableDns }: TimerModalPro
|
|||||||
|
|
||||||
const handleSetTimer = () => {
|
const handleSetTimer = () => {
|
||||||
const duration = hours * 3600 + minutes * 60;
|
const duration = hours * 3600 + minutes * 60;
|
||||||
integrationIds.forEach((integrationId) => {
|
selectedIntegrationIds.forEach((integrationId) => {
|
||||||
disableDns({ duration, integrationId });
|
disableDns({ duration, integrationId });
|
||||||
});
|
});
|
||||||
setHours(0);
|
setHours(0);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
|
|||||||
const [status, setStatus] = useState<{ integrationId: string; enabled: boolean }[]>(
|
const [status, setStatus] = useState<{ integrationId: string; enabled: boolean }[]>(
|
||||||
integrationIds.map((id) => ({ integrationId: id, enabled: false })),
|
integrationIds.map((id) => ({ integrationId: id, enabled: false })),
|
||||||
);
|
);
|
||||||
|
const [selectedIntegrationIds, setSelectedIntegrationIds] = useState<string[]>([]);
|
||||||
const [opened, { close, open }] = useDisclosure(false);
|
const [opened, { close, open }] = useDisclosure(false);
|
||||||
|
|
||||||
const [data] = clientApi.widget.dnsHole.summary.useSuspenseQuery(
|
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 enabledIntegrations = integrationIds.filter((id) => status.find((item) => item.integrationId === id)?.enabled);
|
||||||
const allDisabled = status.every((item) => !item.enabled);
|
const disabledIntegrations = integrationIds.filter(
|
||||||
|
(id) => !status.find((item) => item.integrationId === id)?.enabled,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex h="100%" direction="column" gap={0} p="2.5cqmin">
|
<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">
|
<Flex gap="2.5cqmin">
|
||||||
<Tooltip label={t("widget.dnsHoleControls.controls.enableAll")}>
|
<Tooltip label={t("widget.dnsHoleControls.controls.enableAll")}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => disabledIntegrations.forEach((integrationId) => enableDns({ integrationId }))}
|
||||||
integrationIds.forEach((integrationId) => enableDns({ integrationId }));
|
disabled={disabledIntegrations.length === 0}
|
||||||
}}
|
|
||||||
disabled={allEnabled}
|
|
||||||
variant="light"
|
variant="light"
|
||||||
color="green"
|
color="green"
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -90,17 +91,25 @@ export default function DnsHoleControlsWidget({ options, integrationIds }: Widge
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip label={t("widget.dnsHoleControls.controls.setTimer")}>
|
<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} />
|
<IconClockPause size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip label={t("widget.dnsHoleControls.controls.disableAll")}>
|
<Tooltip label={t("widget.dnsHoleControls.controls.disableAll")}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => enabledIntegrations.forEach((integrationId) => disableDns({ integrationId, duration: 0 }))}
|
||||||
integrationIds.forEach((integrationId) => disableDns({ integrationId, duration: 0 }));
|
disabled={enabledIntegrations.length === 0}
|
||||||
}}
|
|
||||||
disabled={allDisabled}
|
|
||||||
variant="light"
|
variant="light"
|
||||||
color="red"
|
color="red"
|
||||||
fullWidth
|
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"}>
|
<Stack gap="2.5cqmin" flex={1} justify={options.showToggleAllButtons ? "flex-end" : "space-evenly"}>
|
||||||
{data.map((integrationData) =>
|
{data.map((integrationData) => (
|
||||||
ControlsCard(integrationData.integrationId, integrationData.integrationKind, toggleDns, status, open, t),
|
<ControlsCard
|
||||||
)}
|
key={integrationData.integrationId}
|
||||||
|
integrationId={integrationData.integrationId}
|
||||||
|
integrationKind={integrationData.integrationKind}
|
||||||
|
toggleDns={toggleDns}
|
||||||
|
status={status}
|
||||||
|
setSelectedIntegrationIds={setSelectedIntegrationIds}
|
||||||
|
open={open}
|
||||||
|
t={t}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<TimerModal opened={opened} close={close} integrationIds={integrationIds} disableDns={disableDns} />
|
<TimerModal
|
||||||
|
opened={opened}
|
||||||
|
close={close}
|
||||||
|
selectedIntegrationIds={selectedIntegrationIds}
|
||||||
|
disableDns={disableDns}
|
||||||
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ControlsCard = (
|
interface ControlsCardProps {
|
||||||
integrationId: string,
|
integrationId: string;
|
||||||
integrationKind: string,
|
integrationKind: string;
|
||||||
toggleDns: (integrationId: string) => void,
|
toggleDns: (integrationId: string) => void;
|
||||||
status: { integrationId: string; enabled: boolean }[],
|
status: { integrationId: string; enabled: boolean }[];
|
||||||
open: () => void,
|
setSelectedIntegrationIds: (integrationId: string[]) => void;
|
||||||
t: TranslationFunction,
|
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 integrationStatus = status.find((item) => item.integrationId === integrationId);
|
||||||
const isEnabled = integrationStatus?.enabled ?? false;
|
const isEnabled = integrationStatus?.enabled ?? false;
|
||||||
const integrationDef = integrationKind === "piHole" ? integrationDefs.piHole : integrationDefs.adGuardHome;
|
const integrationDef = integrationKind === "piHole" ? integrationDefs.piHole : integrationDefs.adGuardHome;
|
||||||
@@ -149,7 +183,17 @@ const ControlsCard = (
|
|||||||
{t(`widget.dnsHoleControls.controls.${isEnabled ? "enabled" : "disabled"}`)}
|
{t(`widget.dnsHoleControls.controls.${isEnabled ? "enabled" : "disabled"}`)}
|
||||||
</Badge>
|
</Badge>
|
||||||
</UnstyledButton>
|
</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" />
|
<IconClockPause size={20} color="red" />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
Reference in New Issue
Block a user