feat(board): allow to set icon color of widgets (#2228)

Co-authored-by: Andre Silva <asilva01@acuitysso.com>
This commit is contained in:
Andre Silva
2025-02-19 19:45:12 +00:00
committed by GitHub
parent 58babbf88f
commit de5c34ab07
23 changed files with 3790 additions and 38 deletions

View File

@@ -3,29 +3,19 @@
import "../../widgets-common.css";
import { useState } from "react";
import {
ActionIcon,
Badge,
Button,
Card,
Flex,
Image,
ScrollArea,
Stack,
Text,
Tooltip,
UnstyledButton,
} from "@mantine/core";
import { ActionIcon, Badge, Button, Card, Flex, ScrollArea, Stack, Text, Tooltip, UnstyledButton } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { IconCircleFilled, IconClockPause, IconPlayerPlay, IconPlayerStop } from "@tabler/icons-react";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useIntegrationsWithInteractAccess } from "@homarr/auth/client";
import { useRequiredBoard } from "@homarr/boards/context";
import { useIntegrationConnected } from "@homarr/common";
import { integrationDefs } from "@homarr/definitions";
import type { TranslationFunction } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
import { MaskedOrNormalImage } from "@homarr/ui";
import type { widgetKind } from ".";
import type { WidgetComponentProps } from "../../definition";
@@ -39,6 +29,7 @@ export default function DnsHoleControlsWidget({
integrationIds,
isEditMode,
}: WidgetComponentProps<typeof widgetKind>) {
const board = useRequiredBoard();
// DnsHole integrations with interaction permissions
const integrationsWithInteractions = useIntegrationsWithInteractAccess()
.map(({ id }) => id)
@@ -275,6 +266,7 @@ export default function DnsHoleControlsWidget({
setSelectedIntegrationIds={setSelectedIntegrationIds}
open={open}
t={t}
hasIconColor={board.iconColor !== null}
/>
))}
</Stack>
@@ -297,6 +289,7 @@ interface ControlsCardProps {
setSelectedIntegrationIds: (integrationId: string[]) => void;
open: () => void;
t: TranslationFunction;
hasIconColor: boolean;
}
const ControlsCard: React.FC<ControlsCardProps> = ({
@@ -306,6 +299,7 @@ const ControlsCard: React.FC<ControlsCardProps> = ({
setSelectedIntegrationIds,
open,
t,
hasIconColor,
}) => {
const isConnected = useIntegrationConnected(data.integration.updatedAt, { timeout: 30000 });
const isEnabled = data.summary.status ? data.summary.status === "enabled" : undefined;
@@ -313,6 +307,8 @@ const ControlsCard: React.FC<ControlsCardProps> = ({
// Use all factors to infer the state of the action buttons
const controlEnabled = isInteractPermitted && isEnabled !== undefined && isConnected;
const iconUrl = integrationDefs[data.integration.kind].iconUrl;
return (
<Card
className={`dns-hole-controls-integration-item-outer-shell dns-hole-controls-integration-item-${data.integration.id} dns-hole-controls-integration-item-${data.integration.name}`}
@@ -322,13 +318,16 @@ const ControlsCard: React.FC<ControlsCardProps> = ({
radius="2.5cqmin"
>
<Flex className="dns-hole-controls-item-container" gap="4cqmin" align="center" direction="row">
<Image
<MaskedOrNormalImage
imageUrl={iconUrl}
hasColor={hasIconColor}
alt={data.integration.name}
className="dns-hole-controls-item-icon"
src={integrationDefs[data.integration.kind].iconUrl}
w="20cqmin"
h="20cqmin"
fit="contain"
style={{ filter: !isConnected ? "grayscale(100%)" : undefined }}
style={{
height: "20cqmin",
width: "20cqmin",
filter: !isConnected ? "grayscale(100%)" : undefined,
}}
/>
<Flex className="dns-hole-controls-item-data-stack" direction="column" gap="1.5cqmin">
<Text className="dns-hole-controls-item-integration-name" fz="7cqmin">