Use skeleton loading where possible
This commit is contained in:
@@ -1,29 +1,48 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import globalize from 'lib/globalize';
|
||||
import Widget from './Widget';
|
||||
import List from '@mui/material/List';
|
||||
import ActivityListItem from 'apps/dashboard/features/activity/components/ActivityListItem';
|
||||
import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models/activity-log-entry';
|
||||
import { useLogEntries } from 'apps/dashboard/features/activity/api/useLogEntries';
|
||||
import subSeconds from 'date-fns/subSeconds';
|
||||
import Skeleton from '@mui/material/Skeleton';
|
||||
import Stack from '@mui/material/Stack';
|
||||
|
||||
type IProps = {
|
||||
logs?: ActivityLogEntry[];
|
||||
};
|
||||
const ActivityLogWidget = () => {
|
||||
const dayBefore = useMemo(() => (
|
||||
subSeconds(new Date(), 24 * 60 * 60).toISOString()
|
||||
), []);
|
||||
|
||||
const { data: logs, isPending } = useLogEntries({
|
||||
startIndex: 0,
|
||||
limit: 7,
|
||||
minDate: dayBefore,
|
||||
hasUserId: true
|
||||
});
|
||||
|
||||
const ActivityLogWidget = ({ logs }: IProps) => {
|
||||
return (
|
||||
<Widget
|
||||
title={globalize.translate('HeaderActivity')}
|
||||
href='/dashboard/activity?useractivity=true'
|
||||
>
|
||||
<List sx={{ bgcolor: 'background.paper' }}>
|
||||
{logs?.map(entry => (
|
||||
<ActivityListItem
|
||||
key={entry.Id}
|
||||
item={entry}
|
||||
displayShortOverview={true}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
{isPending ? (
|
||||
<Stack spacing={2}>
|
||||
<Skeleton variant='rounded' height={60} />
|
||||
<Skeleton variant='rounded' height={60} />
|
||||
<Skeleton variant='rounded' height={60} />
|
||||
<Skeleton variant='rounded' height={60} />
|
||||
</Stack>
|
||||
) : (
|
||||
<List sx={{ bgcolor: 'background.paper' }}>
|
||||
{logs?.Items?.map(entry => (
|
||||
<ActivityListItem
|
||||
key={entry.Id}
|
||||
item={entry}
|
||||
displayShortOverview={true}
|
||||
/>
|
||||
))}
|
||||
</List>
|
||||
)}
|
||||
</Widget>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import globalize from 'lib/globalize';
|
||||
import Widget from './Widget';
|
||||
import List from '@mui/material/List';
|
||||
import ActivityListItem from 'apps/dashboard/features/activity/components/ActivityListItem';
|
||||
import type { ActivityLogEntry } from '@jellyfin/sdk/lib/generated-client/models';
|
||||
import subSeconds from 'date-fns/subSeconds';
|
||||
import { useLogEntries } from 'apps/dashboard/features/activity/api/useLogEntries';
|
||||
|
||||
type IProps = {
|
||||
alerts?: ActivityLogEntry[];
|
||||
};
|
||||
const AlertsLogWidget = () => {
|
||||
const weekBefore = useMemo(() => (
|
||||
subSeconds(new Date(), 7 * 24 * 60 * 60).toISOString()
|
||||
), []);
|
||||
|
||||
const AlertsLogWidget = ({ alerts }: IProps) => {
|
||||
if (alerts?.length == 0) return null;
|
||||
const { data: alerts, isPending } = useLogEntries({
|
||||
startIndex: 0,
|
||||
limit: 4,
|
||||
minDate: weekBefore,
|
||||
hasUserId: false
|
||||
});
|
||||
|
||||
if (isPending || alerts?.Items?.length == 0) return null;
|
||||
|
||||
return (
|
||||
<Widget
|
||||
@@ -18,7 +26,7 @@ const AlertsLogWidget = ({ alerts }: IProps) => {
|
||||
href='/dashboard/activity?useractivity=false'
|
||||
>
|
||||
<List sx={{ bgcolor: 'background.paper' }}>
|
||||
{alerts?.map(entry => (
|
||||
{alerts?.Items?.map(entry => (
|
||||
<ActivityListItem
|
||||
key={entry.Id}
|
||||
item={entry}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import React from 'react';
|
||||
import globalize from 'lib/globalize';
|
||||
import Widget from './Widget';
|
||||
import type { SessionInfo } from '@jellyfin/sdk/lib/generated-client/models/session-info';
|
||||
import DeviceCard from 'apps/dashboard/features/devices/components/DeviceCard';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import useLiveSessions from 'apps/dashboard/features/sessions/hooks/useLiveSessions';
|
||||
|
||||
type IProps = {
|
||||
devices?: SessionInfo[];
|
||||
};
|
||||
const DevicesWidget = () => {
|
||||
const { data: devices } = useLiveSessions();
|
||||
|
||||
const DevicesWidget = ({ devices }: IProps) => {
|
||||
return (
|
||||
<Widget
|
||||
title={globalize.translate('HeaderDevices')}
|
||||
|
||||
@@ -9,13 +9,11 @@ import React from 'react';
|
||||
|
||||
import MetricCard from 'apps/dashboard/features/metrics/components/MetricCard';
|
||||
import globalize from 'lib/globalize';
|
||||
import type { ItemCounts } from '@jellyfin/sdk/lib/generated-client/models/item-counts';
|
||||
import { useItemCounts } from 'apps/dashboard/features/metrics/api/useItemCounts';
|
||||
|
||||
type IProps = {
|
||||
counts?: ItemCounts;
|
||||
};
|
||||
const ItemCountsWidget = () => {
|
||||
const { data: counts } = useItemCounts();
|
||||
|
||||
const ItemCountsWidget = ({ counts }: IProps) => {
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
|
||||
@@ -6,6 +6,8 @@ import Typography from '@mui/material/Typography';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Button from '@mui/material/Button';
|
||||
import type { SystemInfo } from '@jellyfin/sdk/lib/generated-client/models';
|
||||
import Skeleton from '@mui/material/Skeleton';
|
||||
import { useSystemInfo } from 'hooks/useSystemInfo';
|
||||
|
||||
type IProps = {
|
||||
systemInfo?: SystemInfo;
|
||||
@@ -14,7 +16,9 @@ type IProps = {
|
||||
onShutdownClick?: () => void;
|
||||
};
|
||||
|
||||
const ServerInfoWidget = ({ systemInfo, onScanLibrariesClick, onRestartClick, onShutdownClick }: IProps) => {
|
||||
const ServerInfoWidget = ({ onScanLibrariesClick, onRestartClick, onShutdownClick }: IProps) => {
|
||||
const { data: systemInfo, isPending } = useSystemInfo();
|
||||
|
||||
return (
|
||||
<Widget
|
||||
title={globalize.translate('TabServer')}
|
||||
@@ -32,10 +36,21 @@ const ServerInfoWidget = ({ systemInfo, onScanLibrariesClick, onRestartClick, on
|
||||
<Typography fontWeight='bold'>{globalize.translate('LabelBuildVersion')}</Typography>
|
||||
</Stack>
|
||||
<Stack flexGrow={5} gap={1}>
|
||||
<Typography>{systemInfo?.ServerName}</Typography>
|
||||
<Typography>{systemInfo?.Version}</Typography>
|
||||
<Typography>{__PACKAGE_JSON_VERSION__}</Typography>
|
||||
<Typography>{__JF_BUILD_VERSION__}</Typography>
|
||||
{isPending ? (
|
||||
<>
|
||||
<Skeleton />
|
||||
<Skeleton />
|
||||
<Skeleton />
|
||||
<Skeleton />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Typography>{systemInfo?.ServerName}</Typography>
|
||||
<Typography>{systemInfo?.Version}</Typography>
|
||||
<Typography>{__PACKAGE_JSON_VERSION__}</Typography>
|
||||
<Typography>{__JF_BUILD_VERSION__}</Typography>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -3,13 +3,11 @@ import React from 'react';
|
||||
import StorageListItem from 'apps/dashboard/features/storage/components/StorageListItem';
|
||||
import globalize from 'lib/globalize';
|
||||
import Widget from './Widget';
|
||||
import type { SystemStorageDto } from '@jellyfin/sdk/lib/generated-client/models/system-storage-dto';
|
||||
import { useSystemStorage } from 'apps/dashboard/features/storage/api/useSystemStorage';
|
||||
|
||||
type IProps = {
|
||||
systemStorage?: SystemStorageDto;
|
||||
};
|
||||
const ServerPathWidget = () => {
|
||||
const { data: systemStorage } = useSystemStorage();
|
||||
|
||||
const ServerPathWidget = ({ systemStorage }: IProps) => {
|
||||
return (
|
||||
<Widget
|
||||
title={globalize.translate('HeaderPaths')}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import Page from 'components/Page';
|
||||
import globalize from 'lib/globalize';
|
||||
import Box from '@mui/material/Box';
|
||||
@@ -10,21 +10,14 @@ import AlertsLogWidget from '../components/widgets/AlertsLogWidget';
|
||||
import useTheme from '@mui/material/styles/useTheme';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { useSystemStorage } from '../features/storage/api/useSystemStorage';
|
||||
import subSeconds from 'date-fns/subSeconds';
|
||||
import { useLogEntries } from '../features/activity/api/useLogEntries';
|
||||
import { useSystemInfo } from 'hooks/useSystemInfo';
|
||||
import Loading from 'components/loading/LoadingComponent';
|
||||
import useShutdownServer from '../features/system/api/useShutdownServer';
|
||||
import useRestartServer from '../features/system/api/useRestartServer';
|
||||
import ConfirmDialog from 'components/ConfirmDialog';
|
||||
import useLiveTasks from '../features/tasks/hooks/useLiveTasks';
|
||||
import RunningTasksWidget from '../components/widgets/RunningTasksWidget';
|
||||
import DevicesWidget from '../components/widgets/DevicesWidget';
|
||||
import useLiveSessions from '../features/sessions/hooks/useLiveSessions';
|
||||
import { useStartTask } from '../features/tasks/api/useStartTask';
|
||||
import ItemCountsWidget from '../components/widgets/ItemCountsWidget';
|
||||
import { useItemCounts } from '../features/metrics/api/useItemCounts';
|
||||
|
||||
export const Component = () => {
|
||||
const theme = useTheme();
|
||||
@@ -36,34 +29,7 @@ export const Component = () => {
|
||||
const restartServer = useRestartServer();
|
||||
const shutdownServer = useShutdownServer();
|
||||
|
||||
const { data: tasks, isPending: isTasksPending } = useLiveTasks({ isHidden: false });
|
||||
const { data: devices } = useLiveSessions();
|
||||
|
||||
const dayBefore = useMemo(() => (
|
||||
subSeconds(new Date(), 24 * 60 * 60).toISOString()
|
||||
), []);
|
||||
|
||||
const weekBefore = useMemo(() => (
|
||||
subSeconds(new Date(), 7 * 24 * 60 * 60).toISOString()
|
||||
), []);
|
||||
|
||||
const { data: logs, isPending: isLogsPending } = useLogEntries({
|
||||
startIndex: 0,
|
||||
limit: 7,
|
||||
minDate: dayBefore,
|
||||
hasUserId: true
|
||||
});
|
||||
|
||||
const { data: alerts, isPending: isAlertsPending } = useLogEntries({
|
||||
startIndex: 0,
|
||||
limit: 4,
|
||||
minDate: weekBefore,
|
||||
hasUserId: false
|
||||
});
|
||||
|
||||
const { data: systemStorage, isPending: isSystemStoragePending } = useSystemStorage();
|
||||
const { data: systemInfo, isPending: isSystemInfoPending } = useSystemInfo();
|
||||
const { data: itemCounts, isPending: isItemCountsPending } = useItemCounts();
|
||||
const { data: tasks } = useLiveTasks({ isHidden: false });
|
||||
|
||||
const promptRestart = useCallback(() => {
|
||||
setIsRestartConfirmDialogOpen(true);
|
||||
@@ -101,13 +67,6 @@ export const Component = () => {
|
||||
setIsShutdownConfirmDialogOpen(false);
|
||||
}, [ shutdownServer ]);
|
||||
|
||||
const isPending = isLogsPending || isAlertsPending || isSystemStoragePending
|
||||
|| isSystemInfoPending || isTasksPending || isItemCountsPending;
|
||||
|
||||
if (isPending) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Page
|
||||
id='dashboardPage'
|
||||
@@ -137,35 +96,32 @@ export const Component = () => {
|
||||
<Grid size={{ xs: 12, md: 12, xl: 6 }}>
|
||||
<Stack spacing={3}>
|
||||
<ServerInfoWidget
|
||||
systemInfo={systemInfo}
|
||||
onScanLibrariesClick={onScanLibraries}
|
||||
onRestartClick={promptRestart}
|
||||
onShutdownClick={promptShutdown}
|
||||
/>
|
||||
<ItemCountsWidget counts={itemCounts} />
|
||||
<ItemCountsWidget />
|
||||
<RunningTasksWidget tasks={tasks} />
|
||||
<DevicesWidget devices={devices} />
|
||||
<DevicesWidget />
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, md: 6, lg: 12, xl: 3 }}>
|
||||
<ActivityLogWidget logs={logs?.Items} />
|
||||
<ActivityLogWidget />
|
||||
</Grid>
|
||||
{isMedium || isExtraLarge ? (
|
||||
<Grid size={{ md: 6, xl: 3 }}>
|
||||
<Stack spacing={3}>
|
||||
<AlertsLogWidget alerts={alerts?.Items} />
|
||||
<ServerPathWidget systemStorage={systemStorage} />
|
||||
<AlertsLogWidget />
|
||||
<ServerPathWidget />
|
||||
</Stack>
|
||||
</Grid>
|
||||
) : (
|
||||
<>
|
||||
{(alerts?.Items && alerts.Items.length > 0) && (
|
||||
<Grid size={{ xs: 12, lg: 12 }}>
|
||||
<AlertsLogWidget alerts={alerts?.Items} />
|
||||
</Grid>
|
||||
)}
|
||||
<Grid size={{ xs: 12, lg: 12 }}>
|
||||
<ServerPathWidget systemStorage={systemStorage} />
|
||||
<AlertsLogWidget />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, lg: 12 }}>
|
||||
<ServerPathWidget />
|
||||
</Grid>
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user