Hugely improve Media display by splitting it into 2 different modules

This commit is contained in:
Aj - Thomas
2022-05-05 09:22:44 +02:00
parent b58f15aeec
commit 2149e2e10a
3 changed files with 130 additions and 44 deletions

View File

@@ -1,72 +1,84 @@
import { Indicator, Popover, Box, Center } from '@mantine/core'; import { Indicator, Popover, Box, Center, ScrollArea, Divider } from '@mantine/core';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Calendar } from '@mantine/dates'; import { Calendar } from '@mantine/dates';
import MediaDisplay from './MediaDisplay'; import { RadarrMediaDisplay, SonarrMediaDisplay } from './MediaDisplay';
import { useConfig } from '../../tools/state'; import { useConfig } from '../../tools/state';
import { serviceItem } from '../../tools/types';
export default function CalendarComponent(props: any) { export default function CalendarComponent(props: any) {
const { config } = useConfig(); const { config } = useConfig();
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
const [medias, setMedias] = useState([] as any); const [sonarrMedias, setSonarrMedias] = useState([] as any);
if (medias === undefined) { const [radarrMedias, setRadarrMedias] = useState([] as any);
return <div>ok</div>;
}
useEffect(() => { useEffect(() => {
// Filter only sonarr and radarr services // Filter only sonarr and radarr services
const filtered = config.services.filter( const filtered = config.services.filter(
(service) => service.type === 'Sonarr' || service.type === 'Radarr' (service) => service.type === 'Sonarr' || service.type === 'Radarr'
); );
// Get the url and API key for each service // Get the url and apiKey for all Sonarr and Radarr services
const serviceUrls = filtered.map((service: serviceItem) => ({ const sonarrService = filtered.filter((service) => service.type === 'Sonarr').at(0);
url: service.url, const radarrService = filtered.filter((service) => service.type === 'Radarr').at(0);
apiKey: service.apiKey, const nextMonth = new Date(new Date().setMonth(new Date().getMonth() + 2)).toISOString();
})); if (sonarrService) {
fetch(
// Get the medias from each service `${sonarrService?.url}api/calendar?apikey=${sonarrService?.apiKey}&end=${nextMonth}`
// With no cors ).then((response) => {
// const promises = serviceUrls.map((service) => response.json().then((data) => setSonarrMedias(data));
// fetch('/api/getCalendar', { });
// method: 'POST', }
// body: JSON.stringify({ if (radarrService) {
// apiKey: service.apiKey, fetch(
// remoteUrl: service.url, `${radarrService?.url}api/calendar?apikey=${radarrService?.apiKey}&end=${nextMonth}`
// }), ).then((response) => {
// }).then((response) => console.log(response.json())) response.json().then((data) => setRadarrMedias(data));
// ); });
fetch('http://server:8989/api/calendar?apikey=ea736455118146fea297e6c7465205ce').then( }
(response) => {
response.json().then((data) => setMedias(data));
}
);
}, [config.services]); }, [config.services]);
if (medias === undefined) { if (sonarrMedias === undefined && radarrMedias === undefined) {
return <div>ok</div>; return <Calendar />;
} }
return ( return (
<Calendar <Calendar
onChange={(day: any) => {}} onChange={(day: any) => {}}
renderDay={(renderdate) => <DayComponent renderdate={renderdate} medias={medias} />} renderDay={(renderdate) => (
<DayComponent
renderdate={renderdate}
sonarrmedias={sonarrMedias}
radarrmedias={radarrMedias}
/>
)}
/> />
); );
} }
function DayComponent(props: any) { function DayComponent(props: any) {
const { renderdate, medias }: { renderdate: Date; medias: [] } = props; const {
renderdate,
sonarrmedias,
radarrmedias,
}: { renderdate: Date; sonarrmedias: []; radarrmedias: [] } = props;
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
const day = renderdate.getDate(); const day = renderdate.getDate();
// Itterate over the medias and filter the ones that are on the same day // Itterate over the medias and filter the ones that are on the same day
const filtered = medias.filter((media: any) => { const sonarrFiltered = sonarrmedias.filter((media: any) => {
const date = new Date(media.airDate); const date = new Date(media.airDate);
return date.getDate() === day; // Return true if the date is renerdate without counting hours and minutes
return date.getDate() === day && date.getMonth() === renderdate.getMonth();
}); });
if (filtered.length === 0) { const radarrFiltered = radarrmedias.filter((media: any) => {
const date = new Date(media.airDate);
// Return true if the date is renerdate without counting hours and minutes
return date.getDate() === day && date.getMonth() === renderdate.getMonth();
});
if (sonarrFiltered.length === 0 && radarrFiltered.length === 0) {
return <div>{day}</div>; return <div>{day}</div>;
} }
// TODO: #5 Add the ability to display multiple medias on the same day by looping over the filtered medias for each service type
// And adding a divider between the medias
return ( return (
<Box <Box
@@ -84,7 +96,11 @@ function DayComponent(props: any) {
opened={opened} opened={opened}
target={day} target={day}
> >
<MediaDisplay media={filtered[0]} /> <ScrollArea style={{ height: 400 }}>
{sonarrFiltered.length > 0 && <SonarrMediaDisplay media={sonarrFiltered[0]} />}
<Divider my="xl" />
{radarrFiltered.length > 0 && <RadarrMediaDisplay media={radarrFiltered[0]} />}
</ScrollArea>
</Popover> </Popover>
</Indicator> </Indicator>
</Center> </Center>

View File

@@ -1,4 +1,4 @@
import MediaDisplay from './MediaDisplay'; import { RadarrMediaDisplay } from './MediaDisplay';
export default { export default {
title: 'Media display component', title: 'Media display component',
@@ -64,4 +64,4 @@ export default {
}, },
}; };
export const Default = (args: any) => <MediaDisplay {...args} />; export const Default = (args: any) => <RadarrMediaDisplay {...args} />;

View File

@@ -1,4 +1,5 @@
import { Stack, Image, Group, Title, Badge, Text } from '@mantine/core'; import { Stack, Image, Group, Title, Badge, Text, ActionIcon, Anchor } from '@mantine/core';
import { Link } from 'tabler-icons-react';
export interface IMedia { export interface IMedia {
id: string; id: string;
@@ -9,13 +10,16 @@ export interface IMedia {
genres: string[]; genres: string[];
} }
export default function MediaDisplay(props: any) { export function RadarrMediaDisplay(props: any) {
const { media }: { media: any } = props; const { media }: { media: any } = props;
// Find a poster CoverType
const poster = media.series.images.find((image: any) => image.coverType === 'poster');
// Return a movie poster containting the title and the description // Return a movie poster containting the title and the description
return ( return (
<Group noWrap align="self-start"> <Group noWrap align="self-start">
<Image <Image
src={media.series.images[0].url} fit="cover"
src={poster.url}
alt={media.series.title} alt={media.series.title}
style={{ style={{
maxWidth: 300, maxWidth: 300,
@@ -28,8 +32,74 @@ export default function MediaDisplay(props: any) {
})} })}
> >
<Group direction="column"> <Group direction="column">
<Title order={3}>{media.series.title}</Title> <Group>
<Text>{media.overview}</Text> <Title order={3}>{media.series.title}</Title>
<Anchor href={`https://www.imdb.com/title/${media.series.imdbId}`} target="_blank">
<ActionIcon>
<Link />
</ActionIcon>
</Anchor>
</Group>
<Text
style={{
textAlign: 'center',
color: '#a0aec0',
}}
>
Season {media.seasonNumber} episode {media.episodeNumber}
</Text>
<Text>{media.series.overview}</Text>
</Group>
{/*Add the genres at the bottom of the poster*/}
<Group>
{media.series.genres.map((genre: string, i: number) => (
<Badge key={i}>{genre}</Badge>
))}
</Group>
</Stack>
</Group>
);
}
export function SonarrMediaDisplay(props: any) {
const { media }: { media: any } = props;
// Find a poster CoverType
const poster = media.series.images.find((image: any) => image.coverType === 'poster');
// Return a movie poster containting the title and the description
return (
<Group noWrap align="self-start">
<Image
fit="cover"
src={poster.url}
alt={media.series.title}
style={{
maxWidth: 300,
}}
/>
<Stack
justify="space-between"
sx={(theme) => ({
height: 400,
})}
>
<Group direction="column">
<Group>
<Title order={3}>{media.series.title}</Title>
<Anchor href={`https://www.imdb.com/title/${media.series.imdbId}`} target="_blank">
<ActionIcon>
<Link />
</ActionIcon>
</Anchor>
</Group>
<Text
style={{
textAlign: 'center',
color: '#a0aec0',
}}
>
Season {media.seasonNumber} episode {media.episodeNumber}
</Text>
<Text>{media.series.overview}</Text>
</Group> </Group>
{/*Add the genres at the bottom of the poster*/} {/*Add the genres at the bottom of the poster*/}
<Group> <Group>