bazarr/frontend/src/Series/Episodes/index.tsx

153 lines
4.0 KiB
TypeScript
Raw Normal View History

2021-03-25 14:22:43 +00:00
import {
faAdjust,
faBriefcase,
faCloudUploadAlt,
faHdd,
faSearch,
faSync,
faWrench,
} from "@fortawesome/free-solid-svg-icons";
import React, { FunctionComponent, useMemo, useState } from "react";
2021-03-25 14:22:43 +00:00
import { Container, Row } from "react-bootstrap";
import { Helmet } from "react-helmet";
import { Redirect, RouteComponentProps, withRouter } from "react-router-dom";
import { useEpisodesBy, useProfileBy, useSerieBy } from "../../@redux/hooks";
2021-03-25 14:22:43 +00:00
import { SeriesApi } from "../../apis";
import {
ContentHeader,
ItemEditorModal,
LoadingIndicator,
SeriesUploadModal,
useShowModal,
} from "../../components";
import ItemOverview from "../../generic/ItemOverview";
2021-04-23 16:18:09 +00:00
import { RouterEmptyPath } from "../../special-pages/404";
import { useOnLoadedOnce } from "../../utilites";
2021-03-25 14:22:43 +00:00
import Table from "./table";
interface Params {
id: string;
}
interface Props extends RouteComponentProps<Params> {}
const SeriesEpisodesView: FunctionComponent<Props> = (props) => {
const { match } = props;
const id = Number.parseInt(match.params.id);
const series = useSerieBy(id);
const episodes = useEpisodesBy(id);
const serie = series.content;
2021-03-25 14:22:43 +00:00
const available = episodes.content.length !== 0;
2021-03-25 14:22:43 +00:00
const details = useMemo(
() => [
{
icon: faHdd,
text: `${serie?.episodeFileCount} files`,
2021-03-25 14:22:43 +00:00
},
{
icon: faAdjust,
text: serie?.seriesType ?? "",
2021-03-25 14:22:43 +00:00
},
],
[serie]
2021-03-25 14:22:43 +00:00
);
const showModal = useShowModal();
const [valid, setValid] = useState(true);
useOnLoadedOnce(() => {
if (series.content === null) {
2021-03-25 14:22:43 +00:00
setValid(false);
}
}, series);
2021-03-25 14:22:43 +00:00
const profile = useProfileBy(series.content?.profileId);
2021-03-25 14:22:43 +00:00
if (isNaN(id) || !valid) {
return <Redirect to={RouterEmptyPath}></Redirect>;
}
if (!serie) {
2021-03-25 14:22:43 +00:00
return <LoadingIndicator></LoadingIndicator>;
}
return (
<Container fluid>
<Helmet>
<title>{serie.title} - Bazarr (Series)</title>
2021-03-25 14:22:43 +00:00
</Helmet>
<ContentHeader>
<ContentHeader.Group pos="start">
<ContentHeader.AsyncButton
icon={faSync}
disabled={!available}
promise={() =>
SeriesApi.action({ action: "scan-disk", seriesid: id })
}
>
Scan Disk
</ContentHeader.AsyncButton>
<ContentHeader.AsyncButton
icon={faSearch}
promise={() =>
SeriesApi.action({ action: "search-missing", seriesid: id })
}
disabled={
serie.episodeFileCount === 0 ||
serie.profileId === null ||
2021-03-25 14:22:43 +00:00
!available
}
>
Search
</ContentHeader.AsyncButton>
</ContentHeader.Group>
<ContentHeader.Group pos="end">
<ContentHeader.Button
disabled={serie.episodeFileCount === 0 || !available}
2021-03-25 14:22:43 +00:00
icon={faBriefcase}
onClick={() => showModal("tools", episodes.content)}
2021-03-25 14:22:43 +00:00
>
Tools
</ContentHeader.Button>
<ContentHeader.Button
disabled={
serie.episodeFileCount === 0 ||
serie.profileId === null ||
2021-03-25 14:22:43 +00:00
!available
}
icon={faCloudUploadAlt}
onClick={() => showModal("upload", serie)}
2021-03-25 14:22:43 +00:00
>
Upload
</ContentHeader.Button>
<ContentHeader.Button
icon={faWrench}
onClick={() => showModal("edit", serie)}
2021-03-25 14:22:43 +00:00
>
Edit Series
</ContentHeader.Button>
</ContentHeader.Group>
</ContentHeader>
<Row>
<ItemOverview item={serie} details={details}></ItemOverview>
2021-03-25 14:22:43 +00:00
</Row>
<Row>
<Table serie={series} episodes={episodes} profile={profile}></Table>
2021-03-25 14:22:43 +00:00
</Row>
<ItemEditorModal
modalKey="edit"
submit={(form) => SeriesApi.modify(form)}
></ItemEditorModal>
<SeriesUploadModal
modalKey="upload"
episodes={episodes.content}
></SeriesUploadModal>
2021-03-25 14:22:43 +00:00
</Container>
);
};
export default withRouter(SeriesEpisodesView);