mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 07:25:48 +01:00
🎨 Migrate all wrapper to use WidgetWrapper
This commit is contained in:
@@ -36,11 +36,7 @@ export const AppTile = ({ className, app }: AppTileProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<HomarrCardWrapper className={className}>
|
||||||
{/* TODO: add app menu */}
|
<AppMenu app={app} />
|
||||||
|
|
||||||
<div style={{ position: 'absolute', top: 10, right: 10 }}>
|
|
||||||
<AppMenu app={app} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!app.url || isEditMode ? (
|
{!app.url || isEditMode ? (
|
||||||
<UnstyledButton
|
<UnstyledButton
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { MutableRefObject, RefObject } from 'react';
|
|||||||
import { AppType } from '../../../types/app';
|
import { AppType } from '../../../types/app';
|
||||||
import Widgets from '../../../widgets';
|
import Widgets from '../../../widgets';
|
||||||
import { IWidget, IWidgetDefinition } from '../../../widgets/widgets';
|
import { IWidget, IWidgetDefinition } from '../../../widgets/widgets';
|
||||||
|
import { WidgetWrapper } from '../../../widgets/WidgetWrapper';
|
||||||
import { Tiles } from '../Tiles/tilesDefinitions';
|
import { Tiles } from '../Tiles/tilesDefinitions';
|
||||||
import { GridstackTileWrapper } from '../Tiles/TileWrapper';
|
import { GridstackTileWrapper } from '../Tiles/TileWrapper';
|
||||||
|
|
||||||
@@ -51,7 +52,9 @@ export const WrapperContent = ({ apps, refs, widgets }: WrapperContentProps) =>
|
|||||||
{...widget.shape.location}
|
{...widget.shape.location}
|
||||||
{...widget.shape.size}
|
{...widget.shape.size}
|
||||||
>
|
>
|
||||||
<definition.component className="grid-stack-item-content" widget={widget} />
|
<WidgetWrapper className="grid-stack-item-content" widget={widget} widgetId={widget.id}>
|
||||||
|
<definition.component className="grid-stack-item-content" widget={widget} />
|
||||||
|
</WidgetWrapper>
|
||||||
</GridstackTileWrapper>
|
</GridstackTileWrapper>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { IconClock, IconFileDownload } from '@tabler/icons';
|
import { IconFileDownload } from '@tabler/icons';
|
||||||
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
|
|
||||||
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
|
|
||||||
import { defineWidget } from '../helper';
|
import { defineWidget } from '../helper';
|
||||||
import { IWidget } from '../widgets';
|
import { IWidget } from '../widgets';
|
||||||
|
|
||||||
@@ -19,12 +17,12 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type IBitTorrent = IWidget<typeof definition['id'], typeof definition>;
|
export type IBitTorrent = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface BitTorrentTileProps extends BaseTileProps {
|
interface BitTorrentTileProps {
|
||||||
widget: IBitTorrent; // TODO: change to new type defined through widgetDefinition
|
widget: IBitTorrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BitTorrentTile({ className, widget }: BitTorrentTileProps) {
|
function BitTorrentTile({ widget }: BitTorrentTileProps) {
|
||||||
return <HomarrCardWrapper>Bit Torrent</HomarrCardWrapper>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default definition;
|
export default definition;
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import { Calendar } from '@mantine/dates';
|
|||||||
import { IconCalendarTime } from '@tabler/icons';
|
import { IconCalendarTime } from '@tabler/icons';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
|
|
||||||
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
|
|
||||||
import { useConfigContext } from '../../config/provider';
|
import { useConfigContext } from '../../config/provider';
|
||||||
import { useColorTheme } from '../../tools/color';
|
import { useColorTheme } from '../../tools/color';
|
||||||
import { isToday } from '../../tools/isToday';
|
import { isToday } from '../../tools/isToday';
|
||||||
@@ -33,11 +31,11 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type ICalendarWidget = IWidget<typeof definition['id'], typeof definition>;
|
export type ICalendarWidget = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface CalendarTileProps extends BaseTileProps {
|
interface CalendarTileProps {
|
||||||
widget: ICalendarWidget;
|
widget: ICalendarWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
function CalendarTile({ className, widget }: CalendarTileProps) {
|
function CalendarTile({ widget }: CalendarTileProps) {
|
||||||
const { secondaryColor } = useColorTheme();
|
const { secondaryColor } = useColorTheme();
|
||||||
const { name: configName } = useConfigContext();
|
const { name: configName } = useConfigContext();
|
||||||
const { classes, cx } = useStyles(secondaryColor);
|
const { classes, cx } = useStyles(secondaryColor);
|
||||||
@@ -57,35 +55,33 @@ function CalendarTile({ className, widget }: CalendarTileProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className} p={6}>
|
<Calendar
|
||||||
<Calendar
|
month={month}
|
||||||
month={month}
|
onMonthChange={setMonth}
|
||||||
onMonthChange={setMonth}
|
size="xs"
|
||||||
size="xs"
|
fullWidth
|
||||||
fullWidth
|
onChange={() => {}}
|
||||||
onChange={() => {}}
|
firstDayOfWeek={widget.properties.sundayStart ? 'sunday' : 'monday'}
|
||||||
firstDayOfWeek={widget.properties.sundayStart ? 'sunday' : 'monday'}
|
dayStyle={(date) => ({
|
||||||
dayStyle={(date) => ({
|
margin: 1,
|
||||||
margin: 1,
|
backgroundColor: isToday(date)
|
||||||
backgroundColor: isToday(date)
|
? colorScheme === 'dark'
|
||||||
? colorScheme === 'dark'
|
? colors.dark[5]
|
||||||
? colors.dark[5]
|
: colors.gray[0]
|
||||||
: colors.gray[0]
|
: undefined,
|
||||||
: undefined,
|
})}
|
||||||
})}
|
styles={{
|
||||||
styles={{
|
calendarHeader: {
|
||||||
calendarHeader: {
|
marginRight: 40,
|
||||||
marginRight: 40,
|
marginLeft: 40,
|
||||||
marginLeft: 40,
|
},
|
||||||
},
|
}}
|
||||||
}}
|
allowLevelChange={false}
|
||||||
allowLevelChange={false}
|
dayClassName={(_, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
|
||||||
dayClassName={(_, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
|
renderDay={(date) => (
|
||||||
renderDay={(date) => (
|
<CalendarDay date={date} medias={getReleasedMediasForDate(medias, date)} />
|
||||||
<CalendarDay date={date} medias={getReleasedMediasForDate(medias, date)} />
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
|
||||||
</HomarrCardWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ import { createStyles, Group, Title } from '@mantine/core';
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
|
|
||||||
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
|
|
||||||
import { WidgetsMenu } from '../../components/Dashboard/Tiles/Widgets/WidgetsMenu';
|
|
||||||
import { useConfigContext } from '../../config/provider';
|
import { useConfigContext } from '../../config/provider';
|
||||||
import { defineWidget } from '../helper';
|
import { defineWidget } from '../helper';
|
||||||
import { IWidget } from '../widgets';
|
import { IWidget } from '../widgets';
|
||||||
@@ -49,11 +46,11 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type IDashDotTile = IWidget<typeof definition['id'], typeof definition>;
|
export type IDashDotTile = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface DashDotTileProps extends BaseTileProps {
|
interface DashDotTileProps {
|
||||||
widget: IDashDotTile; // TODO: change to new type defined through widgetDefinition
|
widget: IDashDotTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DashDotTile({ widget, className }: DashDotTileProps) {
|
function DashDotTile({ widget }: DashDotTileProps) {
|
||||||
const { classes } = useDashDotTileStyles();
|
const { classes } = useDashDotTileStyles();
|
||||||
const { t } = useTranslation('modules/dashdot');
|
const { t } = useTranslation('modules/dashdot');
|
||||||
|
|
||||||
@@ -76,23 +73,6 @@ function DashDotTile({ widget, className }: DashDotTileProps) {
|
|||||||
</Title>
|
</Title>
|
||||||
);
|
);
|
||||||
|
|
||||||
const menu = (
|
|
||||||
// TODO: add widgetWrapper that is generic and uses the definition
|
|
||||||
<WidgetsMenu widget={widget} integration={definition.id} />
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!dashDotUrl) {
|
|
||||||
return (
|
|
||||||
<HomarrCardWrapper className={className}>
|
|
||||||
{menu}
|
|
||||||
<div>
|
|
||||||
{heading}
|
|
||||||
<p>{t('card.errors.noApp')}</p>
|
|
||||||
</div>
|
|
||||||
</HomarrCardWrapper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isCompact = widget?.properties.useCompactView ?? false;
|
const isCompact = widget?.properties.useCompactView ?? false;
|
||||||
|
|
||||||
const isCompactStorageVisible = graphs?.some((g) => g.id === 'storage' && isCompact);
|
const isCompactStorageVisible = graphs?.some((g) => g.id === 'storage' && isCompact);
|
||||||
@@ -104,8 +84,7 @@ function DashDotTile({ widget, className }: DashDotTileProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<>
|
||||||
{menu}
|
|
||||||
{heading}
|
{heading}
|
||||||
{!info && <p>{t('card.errors.noInformation')}</p>}
|
{!info && <p>{t('card.errors.noInformation')}</p>}
|
||||||
{info && (
|
{info && (
|
||||||
@@ -126,7 +105,7 @@ function DashDotTile({ widget, className }: DashDotTileProps) {
|
|||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</HomarrCardWrapper>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import { Center, Stack, Text, Title } from '@mantine/core';
|
import { Center, Stack, Text, Title } from '@mantine/core';
|
||||||
|
import { IconClock } from '@tabler/icons';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
|
|
||||||
import { WidgetsMenu } from '../../components/Dashboard/Tiles/Widgets/WidgetsMenu';
|
|
||||||
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
|
|
||||||
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
|
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
|
||||||
import { defineWidget } from '../helper';
|
import { defineWidget } from '../helper';
|
||||||
import { IWidget } from '../widgets';
|
import { IWidget } from '../widgets';
|
||||||
import { IconClock } from '@tabler/icons';
|
|
||||||
|
|
||||||
const definition = defineWidget({
|
const definition = defineWidget({
|
||||||
id: 'date',
|
id: 'date',
|
||||||
@@ -29,25 +26,21 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type IDateWidget = IWidget<typeof definition['id'], typeof definition>;
|
export type IDateWidget = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface DateTileProps extends BaseTileProps {
|
interface DateTileProps {
|
||||||
widget: IDateWidget; // TODO: change to new type defined through widgetDefinition
|
widget: IDateWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DateTile({ className, widget }: DateTileProps) {
|
function DateTile({ widget }: DateTileProps) {
|
||||||
const date = useDateState();
|
const date = useDateState();
|
||||||
const formatString = widget.properties.display24HourFormat ? 'HH:mm' : 'h:mm A';
|
const formatString = widget.properties.display24HourFormat ? 'HH:mm' : 'h:mm A';
|
||||||
|
|
||||||
// TODO: add widgetWrapper that is generic and uses the definition
|
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<Center style={{ height: '100%' }}>
|
||||||
<WidgetsMenu integration={definition.id} widget={widget} />
|
<Stack spacing="xs">
|
||||||
<Center style={{ height: '100%' }}>
|
<Title>{dayjs(date).format(formatString)}</Title>
|
||||||
<Stack spacing="xs">
|
<Text size="lg">{dayjs(date).format('dddd, MMMM D')}</Text>
|
||||||
<Title>{dayjs(date).format(formatString)}</Title>
|
</Stack>
|
||||||
<Text size="lg">{dayjs(date).format('dddd, MMMM D')}</Text>
|
</Center>
|
||||||
</Stack>
|
|
||||||
</Center>
|
|
||||||
</HomarrCardWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { IconArrowsUpDown, IconClock } from '@tabler/icons';
|
import { IconArrowsUpDown } from '@tabler/icons';
|
||||||
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
|
|
||||||
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
|
|
||||||
import { defineWidget } from '../helper';
|
import { defineWidget } from '../helper';
|
||||||
import { IWidget } from '../widgets';
|
import { IWidget } from '../widgets';
|
||||||
|
|
||||||
@@ -20,12 +18,12 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type ITorrentNetworkTraffic = IWidget<typeof definition['id'], typeof definition>;
|
export type ITorrentNetworkTraffic = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface TorrentNetworkTrafficTileProps extends BaseTileProps {
|
interface TorrentNetworkTrafficTileProps {
|
||||||
widget: ITorrentNetworkTraffic; // TODO: change to new type defined through widgetDefinition
|
widget: ITorrentNetworkTraffic;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TorrentNetworkTrafficTile({ className, widget }: TorrentNetworkTrafficTileProps) {
|
function TorrentNetworkTrafficTile({ widget }: TorrentNetworkTrafficTileProps) {
|
||||||
return <HomarrCardWrapper>TorrentNetworkTraffic</HomarrCardWrapper>;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default definition;
|
export default definition;
|
||||||
|
|||||||
@@ -16,16 +16,14 @@ import { useElementSize } from '@mantine/hooks';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import duration from 'dayjs/plugin/duration';
|
import duration from 'dayjs/plugin/duration';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { UsenetQueueList } from './UsenetQueueList';
|
|
||||||
import { UsenetHistoryList } from './UsenetHistoryList';
|
|
||||||
import { BaseTileProps } from '../../components/Dashboard/Tiles/type';
|
|
||||||
import { AppIntegrationType } from '../../types/app';
|
|
||||||
import { useConfigContext } from '../../config/provider';
|
import { useConfigContext } from '../../config/provider';
|
||||||
import { useGetUsenetInfo, usePauseUsenetQueue, useResumeUsenetQueue } from '../../tools/hooks/api';
|
import { useGetUsenetInfo, usePauseUsenetQueue, useResumeUsenetQueue } from '../../tools/hooks/api';
|
||||||
import { HomarrCardWrapper } from '../../components/Dashboard/Tiles/HomarrCardWrapper';
|
|
||||||
import { humanFileSize } from '../../tools/humanFileSize';
|
import { humanFileSize } from '../../tools/humanFileSize';
|
||||||
|
import { AppIntegrationType } from '../../types/app';
|
||||||
import { defineWidget } from '../helper';
|
import { defineWidget } from '../helper';
|
||||||
import { IWidget } from '../widgets';
|
import { IWidget } from '../widgets';
|
||||||
|
import { UsenetHistoryList } from './UsenetHistoryList';
|
||||||
|
import { UsenetQueueList } from './UsenetQueueList';
|
||||||
|
|
||||||
dayjs.extend(duration);
|
dayjs.extend(duration);
|
||||||
|
|
||||||
@@ -46,15 +44,14 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type IWeatherWidget = IWidget<typeof definition['id'], typeof definition>;
|
export type IWeatherWidget = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface UseNetTileProps extends BaseTileProps {}
|
interface UseNetTileProps {}
|
||||||
|
|
||||||
function UseNetTile({ className }: UseNetTileProps) {
|
function UseNetTile({}: UseNetTileProps) {
|
||||||
const { t } = useTranslation('modules/usenet');
|
const { t } = useTranslation('modules/usenet');
|
||||||
const { config } = useConfigContext();
|
const { config } = useConfigContext();
|
||||||
const downloadApps =
|
const downloadApps =
|
||||||
config?.apps.filter(
|
config?.apps.filter((x) => x.integration && downloadAppTypes.includes(x.integration.type)) ??
|
||||||
(x) => x.integration && downloadAppTypes.includes(x.integration.type)
|
[];
|
||||||
) ?? [];
|
|
||||||
|
|
||||||
const [selectedAppId, setSelectedApp] = useState<string | null>(downloadApps[0]?.id);
|
const [selectedAppId, setSelectedApp] = useState<string | null>(downloadApps[0]?.id);
|
||||||
const { data } = useGetUsenetInfo({ appId: selectedAppId! });
|
const { data } = useGetUsenetInfo({ appId: selectedAppId! });
|
||||||
@@ -70,14 +67,12 @@ function UseNetTile({ className }: UseNetTileProps) {
|
|||||||
|
|
||||||
if (downloadApps.length === 0) {
|
if (downloadApps.length === 0) {
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<Stack>
|
||||||
<Stack>
|
<Title order={3}>{t('card.errors.noDownloadClients.title')}</Title>
|
||||||
<Title order={3}>{t('card.errors.noDownloadClients.title')}</Title>
|
<Group>
|
||||||
<Group>
|
<Text>{t('card.errors.noDownloadClients.text')}</Text>
|
||||||
<Text>{t('card.errors.noDownloadClients.text')}</Text>
|
</Group>
|
||||||
</Group>
|
</Stack>
|
||||||
</Stack>
|
|
||||||
</HomarrCardWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,50 +84,48 @@ function UseNetTile({ className }: UseNetTileProps) {
|
|||||||
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
|
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<Tabs keepMounted={false} defaultValue="queue">
|
||||||
<Tabs keepMounted={false} defaultValue="queue">
|
<Tabs.List ref={ref} mb="md" style={{ flex: 1 }} grow>
|
||||||
<Tabs.List ref={ref} mb="md" style={{ flex: 1 }} grow>
|
<Tabs.Tab value="queue">{t('tabs.queue')}</Tabs.Tab>
|
||||||
<Tabs.Tab value="queue">{t('tabs.queue')}</Tabs.Tab>
|
<Tabs.Tab value="history">{t('tabs.history')}</Tabs.Tab>
|
||||||
<Tabs.Tab value="history">{t('tabs.history')}</Tabs.Tab>
|
{data && (
|
||||||
{data && (
|
<Group position="right" ml="auto">
|
||||||
<Group position="right" ml="auto">
|
{width > MIN_WIDTH_MOBILE && (
|
||||||
{width > MIN_WIDTH_MOBILE && (
|
<>
|
||||||
<>
|
<Badge>{humanFileSize(data?.speed)}/s</Badge>
|
||||||
<Badge>{humanFileSize(data?.speed)}/s</Badge>
|
<Badge>
|
||||||
<Badge>
|
{t('info.sizeLeft')}: {humanFileSize(data?.sizeLeft)}
|
||||||
{t('info.sizeLeft')}: {humanFileSize(data?.sizeLeft)}
|
</Badge>
|
||||||
</Badge>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
</Group>
|
||||||
</Group>
|
|
||||||
)}
|
|
||||||
</Tabs.List>
|
|
||||||
{downloadApps.length > 1 && (
|
|
||||||
<Select
|
|
||||||
value={selectedAppId}
|
|
||||||
onChange={setSelectedApp}
|
|
||||||
ml="xs"
|
|
||||||
data={downloadApps.map((app) => ({ value: app.id, label: app.name }))}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
<Tabs.Panel value="queue">
|
</Tabs.List>
|
||||||
<UsenetQueueList appId={selectedAppId} />
|
{downloadApps.length > 1 && (
|
||||||
{!data ? null : data.paused ? (
|
<Select
|
||||||
<Button uppercase onClick={() => resume()} radius="xl" size="xs" fullWidth mt="sm">
|
value={selectedAppId}
|
||||||
<IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')}
|
onChange={setSelectedApp}
|
||||||
</Button>
|
ml="xs"
|
||||||
) : (
|
data={downloadApps.map((app) => ({ value: app.id, label: app.name }))}
|
||||||
<Button uppercase onClick={() => pause()} radius="xl" size="xs" fullWidth mt="sm">
|
/>
|
||||||
<IconPlayerPause size={12} style={{ marginRight: 5 }} />{' '}
|
)}
|
||||||
{dayjs.duration(data.eta, 's').format('HH:mm')}
|
<Tabs.Panel value="queue">
|
||||||
</Button>
|
<UsenetQueueList appId={selectedAppId} />
|
||||||
)}
|
{!data ? null : data.paused ? (
|
||||||
</Tabs.Panel>
|
<Button uppercase onClick={() => resume()} radius="xl" size="xs" fullWidth mt="sm">
|
||||||
<Tabs.Panel value="history" style={{ display: 'flex', flexDirection: 'column' }}>
|
<IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')}
|
||||||
<UsenetHistoryList appId={selectedAppId} />
|
</Button>
|
||||||
</Tabs.Panel>
|
) : (
|
||||||
</Tabs>
|
<Button uppercase onClick={() => pause()} radius="xl" size="xs" fullWidth mt="sm">
|
||||||
</HomarrCardWrapper>
|
<IconPlayerPause size={12} style={{ marginRight: 5 }} />{' '}
|
||||||
|
{dayjs.duration(data.eta, 's').format('HH:mm')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Tabs.Panel>
|
||||||
|
<Tabs.Panel value="history" style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<UsenetHistoryList appId={selectedAppId} />
|
||||||
|
</Tabs.Panel>
|
||||||
|
</Tabs>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,16 +32,16 @@ const definition = defineWidget({
|
|||||||
|
|
||||||
export type IWeatherWidget = IWidget<typeof definition['id'], typeof definition>;
|
export type IWeatherWidget = IWidget<typeof definition['id'], typeof definition>;
|
||||||
|
|
||||||
interface WeatherTileProps extends BaseTileProps {
|
interface WeatherTileProps {
|
||||||
widget: IWeatherWidget;
|
widget: IWeatherWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
function WeatherTile({ className, widget }: WeatherTileProps) {
|
function WeatherTile({ widget }: WeatherTileProps) {
|
||||||
const { data: weather, isLoading, isError } = useWeatherForCity(widget.properties.location);
|
const { data: weather, isLoading, isError } = useWeatherForCity(widget.properties.location);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<>
|
||||||
<Skeleton height={40} width={100} mb="xl" />
|
<Skeleton height={40} width={100} mb="xl" />
|
||||||
<Group noWrap>
|
<Group noWrap>
|
||||||
<Skeleton height={50} circle />
|
<Skeleton height={50} circle />
|
||||||
@@ -50,58 +50,53 @@ function WeatherTile({ className, widget }: WeatherTileProps) {
|
|||||||
<Skeleton height={25} width={70} />
|
<Skeleton height={25} width={70} />
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</HomarrCardWrapper>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<Center>
|
||||||
<Center>
|
<Text weight={500}>An error occured</Text>
|
||||||
<Text weight={500}>An error occured</Text>
|
</Center>
|
||||||
</Center>
|
|
||||||
</HomarrCardWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add widgetWrapper that is generic and uses the definition
|
// TODO: add widgetWrapper that is generic and uses the definition
|
||||||
return (
|
return (
|
||||||
<HomarrCardWrapper className={className}>
|
<Center style={{ height: '100%' }}>
|
||||||
<WidgetsMenu integration={definition.id} widget={widget} />
|
<Group spacing="md" noWrap align="center">
|
||||||
<Center style={{ height: '100%' }}>
|
<WeatherIcon code={weather!.current_weather.weathercode} />
|
||||||
<Group spacing="md" noWrap align="center">
|
<Stack p={0} spacing={4}>
|
||||||
<WeatherIcon code={weather!.current_weather.weathercode} />
|
<Title order={2}>
|
||||||
<Stack p={0} spacing={4}>
|
{getPerferedUnit(
|
||||||
<Title order={2}>
|
weather!.current_weather.temperature,
|
||||||
{getPerferedUnit(
|
widget.properties.displayInFahrenheit
|
||||||
weather!.current_weather.temperature,
|
)}
|
||||||
widget.properties.displayInFahrenheit
|
</Title>
|
||||||
)}
|
<Group spacing="xs" noWrap>
|
||||||
</Title>
|
<div>
|
||||||
<Group spacing="xs" noWrap>
|
<span>
|
||||||
<div>
|
{getPerferedUnit(
|
||||||
<span>
|
weather!.daily.temperature_2m_max[0],
|
||||||
{getPerferedUnit(
|
widget.properties.displayInFahrenheit
|
||||||
weather!.daily.temperature_2m_max[0],
|
)}
|
||||||
widget.properties.displayInFahrenheit
|
</span>
|
||||||
)}
|
<IconArrowUpRight size={16} style={{ right: 15 }} />
|
||||||
</span>
|
</div>
|
||||||
<IconArrowUpRight size={16} style={{ right: 15 }} />
|
<div>
|
||||||
</div>
|
<span>
|
||||||
<div>
|
{getPerferedUnit(
|
||||||
<span>
|
weather!.daily.temperature_2m_min[0],
|
||||||
{getPerferedUnit(
|
widget.properties.displayInFahrenheit
|
||||||
weather!.daily.temperature_2m_min[0],
|
)}
|
||||||
widget.properties.displayInFahrenheit
|
</span>
|
||||||
)}
|
<IconArrowDownRight size={16} />
|
||||||
</span>
|
</div>
|
||||||
<IconArrowDownRight size={16} />
|
</Group>
|
||||||
</div>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Center>
|
||||||
</Group>
|
|
||||||
</Center>
|
|
||||||
</HomarrCardWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user