Compare commits
8 Commits
main
...
dark-mode-
| Author | SHA1 | Date | |
|---|---|---|---|
| 62efc65c5b | |||
| 1b791d11ca | |||
| eabfeb7ee1 | |||
| cc2a137ec3 | |||
| 0ea5a49786 | |||
| 99b3b55400 | |||
| 9bbe3b539c | |||
| 93087f4963 |
BIN
screenshots/CVMatching.png
Normal file
BIN
screenshots/CVMatching.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
screenshots/ComicDetail.png
Normal file
BIN
screenshots/ComicDetail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 976 KiB |
BIN
screenshots/DC++Searching.png
Normal file
BIN
screenshots/DC++Searching.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
screenshots/Dashboard.png
Normal file
BIN
screenshots/Dashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 MiB |
BIN
screenshots/Import.png
Normal file
BIN
screenshots/Import.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 586 KiB |
BIN
screenshots/Library.png
Normal file
BIN
screenshots/Library.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 MiB |
@@ -278,9 +278,9 @@ export const AcquisitionPanel = (
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="column is-three-fifths">
|
<div className="">
|
||||||
<article className="message is-info">
|
<article className="">
|
||||||
<div className="message-body is-size-6 is-family-secondary">
|
<div className="">
|
||||||
AirDC++ is not configured. Please configure it in{" "}
|
AirDC++ is not configured. Please configure it in{" "}
|
||||||
<code>Settings > AirDC++ > Connection</code>.
|
<code>Settings > AirDC++ > Connection</code>.
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { Menu } from "./ActionMenu/Menu";
|
|||||||
import { ArchiveOperations } from "./Tabs/ArchiveOperations";
|
import { ArchiveOperations } from "./Tabs/ArchiveOperations";
|
||||||
import { ComicInfoXML } from "./Tabs/ComicInfoXML";
|
import { ComicInfoXML } from "./Tabs/ComicInfoXML";
|
||||||
import AcquisitionPanel from "./AcquisitionPanel";
|
import AcquisitionPanel from "./AcquisitionPanel";
|
||||||
|
import TorrentSearchPanel from "./TorrentSearchPanel";
|
||||||
import DownloadsPanel from "./DownloadsPanel";
|
import DownloadsPanel from "./DownloadsPanel";
|
||||||
import { VolumeInformation } from "./Tabs/VolumeInformation";
|
import { VolumeInformation } from "./Tabs/VolumeInformation";
|
||||||
|
|
||||||
@@ -350,7 +351,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
name: "Torrent Search",
|
name: "Torrent Search",
|
||||||
content: <>Torrents</>,
|
content: <TorrentSearchPanel />,
|
||||||
shouldShow: true,
|
shouldShow: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const ComicVineDetails = (props): ReactElement => {
|
|||||||
<div className="min-w-fit">
|
<div className="min-w-fit">
|
||||||
<Card
|
<Card
|
||||||
imageUrl={data.volumeInformation.image.thumb_url}
|
imageUrl={data.volumeInformation.image.thumb_url}
|
||||||
orientation={"vertical-2"}
|
orientation={"cover-only"}
|
||||||
hasDetails={false}
|
hasDetails={false}
|
||||||
// cardContainerStyle={{ maxWidth: 200 }}
|
// cardContainerStyle={{ maxWidth: 200 }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
77
src/client/components/ComicDetail/TorrentSearchPanel.tsx
Normal file
77
src/client/components/ComicDetail/TorrentSearchPanel.tsx
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import React, { useCallback, ReactElement, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Form, Field } from "react-final-form";
|
||||||
|
import { PROWLARR_SERVICE_BASE_URI } from "../../constants/endpoints";
|
||||||
|
|
||||||
|
export const TorrentSearchPanel = (props): ReactElement => {
|
||||||
|
const [prowlarrSettingsData, setProwlarrSettingsData] = useState({});
|
||||||
|
|
||||||
|
const { data } = useQuery({
|
||||||
|
queryFn: async () =>
|
||||||
|
axios({
|
||||||
|
url: `${PROWLARR_SERVICE_BASE_URI}/search`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
port: "9696",
|
||||||
|
apiKey: "c4f42e265fb044dc81f7e88bd41c3367",
|
||||||
|
offset: 0,
|
||||||
|
categories: [7030],
|
||||||
|
query: "the darkness",
|
||||||
|
host: "localhost",
|
||||||
|
limit: 100,
|
||||||
|
type: "search",
|
||||||
|
indexerIds: [2],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
queryKey: ["prowlarrSettingsData"],
|
||||||
|
});
|
||||||
|
console.log(data?.data);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="mt-5">
|
||||||
|
<Form
|
||||||
|
onSubmit={() => {}}
|
||||||
|
initialValues={{}}
|
||||||
|
render={({ handleSubmit, form, submitting, pristine, values }) => (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Field name="issueName">
|
||||||
|
{({ input, meta }) => {
|
||||||
|
return (
|
||||||
|
<div className="max-w-fit">
|
||||||
|
<div className="flex flex-row bg-slate-300 dark:bg-slate-400 rounded-l-lg">
|
||||||
|
<div className="w-10 pl-2 pt-1 text-gray-400 dark:text-gray-200">
|
||||||
|
<i className="icon-[solar--magnifer-bold-duotone] h-7 w-7" />
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
{...input}
|
||||||
|
className="dark:bg-slate-400 bg-slate-300 py-2 px-2 rounded-l-md border-gray-300 h-10 min-w-full dark:text-slate-800 sm:text-md sm:leading-5 focus:outline-none focus:shadow-outline-blue focus:border-blue-300"
|
||||||
|
placeholder="Enter a search term"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="sm:mt-0 min-w-fit rounded-r-lg border border-green-400 dark:border-green-200 bg-green-200 px-3 py-1 text-gray-500 hover:bg-transparent hover:text-green-600 focus:outline-none focus:ring active:text-indigo-500"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
Search Indexer
|
||||||
|
<div className="h-5 w-5 ml-1">
|
||||||
|
<i className="h-6 w-6 icon-[solar--magnet-bold-duotone]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Field>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TorrentSearchPanel;
|
||||||
@@ -5,7 +5,6 @@ import { WantedComicsList } from "./WantedComicsList";
|
|||||||
import { VolumeGroups } from "./VolumeGroups";
|
import { VolumeGroups } from "./VolumeGroups";
|
||||||
import { LibraryStatistics } from "./LibraryStatistics";
|
import { LibraryStatistics } from "./LibraryStatistics";
|
||||||
import { PullList } from "./PullList";
|
import { PullList } from "./PullList";
|
||||||
import { getLibraryStatistics } from "../../actions/comicinfo.actions";
|
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { LIBRARY_SERVICE_BASE_URI } from "../../constants/endpoints";
|
import { LIBRARY_SERVICE_BASE_URI } from "../../constants/endpoints";
|
||||||
@@ -54,16 +53,23 @@ export const Dashboard = (): ReactElement => {
|
|||||||
queryKey: ["volumeGroups"],
|
queryKey: ["volumeGroups"],
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
const { data: statistics } = useQuery({
|
||||||
// const libraryStatistics = useSelector(
|
queryFn: async () =>
|
||||||
// (state: RootState) => state.comicInfo.libraryStatistics,
|
await axios({
|
||||||
// );
|
url: `${LIBRARY_SERVICE_BASE_URI}/libraryStatistics`,
|
||||||
|
method: "GET",
|
||||||
|
}),
|
||||||
|
queryKey: ["libraryStatistics"],
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-full">
|
<div className="container mx-auto max-w-full">
|
||||||
<PullList />
|
<PullList />
|
||||||
{recentComics && <RecentlyImported comics={recentComics?.data.docs} />}
|
{recentComics && <RecentlyImported comics={recentComics?.data.docs} />}
|
||||||
{/* Wanted comics */}
|
{/* Wanted comics */}
|
||||||
<WantedComicsList comics={wantedComics?.data?.docs} />
|
<WantedComicsList comics={wantedComics?.data?.docs} />
|
||||||
|
{/* Library Statistics */}
|
||||||
|
{statistics && <LibraryStatistics stats={statistics?.data} />}
|
||||||
{/* Volume groups */}
|
{/* Volume groups */}
|
||||||
<VolumeGroups volumeGroups={volumeGroups?.data} />
|
<VolumeGroups volumeGroups={volumeGroups?.data} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,113 +1,99 @@
|
|||||||
import React, { ReactElement, useEffect } from "react";
|
import React, { ReactElement, useEffect } from "react";
|
||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
import { isEmpty, isUndefined, map } from "lodash";
|
import { isEmpty, isUndefined, map } from "lodash";
|
||||||
|
import Header from "../shared/Header";
|
||||||
|
|
||||||
export const LibraryStatistics = (
|
export const LibraryStatistics = (
|
||||||
props: ILibraryStatisticsProps,
|
props: ILibraryStatisticsProps,
|
||||||
): ReactElement => {
|
): ReactElement => {
|
||||||
// const { stats } = props;
|
const { stats } = props;
|
||||||
return (
|
return (
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<h4 className="title is-4">
|
<Header
|
||||||
<i className="fa-solid fa-chart-simple"></i> Your Library In Numbers
|
headerContent="Your Library In Numbers"
|
||||||
</h4>
|
subHeaderContent={
|
||||||
<p className="subtitle is-7">A brief snapshot of your library.</p>
|
<span className="text-md">A brief snapshot of your library.</span>
|
||||||
<div className="columns is-multiline">
|
}
|
||||||
<div className="column is-narrow is-two-quarter">
|
iconClassNames="fa-solid fa-binoculars mr-2"
|
||||||
<dl className="box">
|
/>
|
||||||
<dd className="is-size-4">
|
|
||||||
<span className="has-text-weight-bold">
|
<div className="mt-3">
|
||||||
{props.stats.totalDocuments}
|
<div className="flex flex-row gap-5">
|
||||||
</span>{" "}
|
<div className="flex flex-col rounded-lg bg-green-100 dark:bg-green-200 px-4 py-6 text-center">
|
||||||
files
|
<dt className="text-lg font-medium text-gray-500">Library size</dt>
|
||||||
|
<dd className="text-3xl text-green-600 md:text-5xl">
|
||||||
|
{props.stats.totalDocuments} files
|
||||||
</dd>
|
</dd>
|
||||||
<dd className="is-size-4">
|
<dd>
|
||||||
Library size
|
<span className="text-2xl text-green-600">
|
||||||
<span className="has-text-weight-bold">
|
|
||||||
{" "}
|
|
||||||
{props.stats.comicDirectorySize &&
|
{props.stats.comicDirectorySize &&
|
||||||
prettyBytes(props.stats.comicDirectorySize)}
|
prettyBytes(props.stats.comicDirectorySize)}
|
||||||
</span>
|
</span>
|
||||||
</dd>
|
</dd>
|
||||||
|
</div>
|
||||||
|
{/* comicinfo and comicvine tagged issues */}
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
{!isUndefined(props.stats.statistics) &&
|
{!isUndefined(props.stats.statistics) &&
|
||||||
!isEmpty(props.stats.statistics[0].issues) && (
|
!isEmpty(props.stats.statistics[0].issues) && (
|
||||||
<dd className="is-size-6">
|
<div className="flex flex-col h-fit rounded-lg bg-green-100 dark:bg-green-200 px-4 py-3 text-center">
|
||||||
<span className="has-text-weight-bold">
|
<span className="text-xl">
|
||||||
{props.stats.statistics[0].issues.length}
|
{props.stats.statistics[0].issues.length}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
tagged with ComicVine
|
tagged with ComicVine
|
||||||
</dd>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isUndefined(props.stats.statistics) &&
|
{!isUndefined(props.stats.statistics) &&
|
||||||
!isEmpty(props.stats.statistics[0].issuesWithComicInfoXML) && (
|
!isEmpty(props.stats.statistics[0].issuesWithComicInfoXML) && (
|
||||||
<dd className="is-size-6">
|
<div className="flex flex-col h-fit rounded-lg bg-green-100 dark:bg-green-200 px-4 py-3 text-center">
|
||||||
<span className="has-text-weight-bold">
|
<span className="text-xl">
|
||||||
{props.stats.statistics[0].issuesWithComicInfoXML.length}
|
{props.stats.statistics[0].issuesWithComicInfoXML.length}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
with
|
|
||||||
<span className="tag is-warning has-text-weight-bold mr-2 ml-1">
|
<span className="tag is-warning has-text-weight-bold mr-2 ml-1">
|
||||||
ComicInfo.xml
|
with ComicInfo.xml
|
||||||
</span>
|
</span>
|
||||||
</dd>
|
</div>
|
||||||
)}
|
)}
|
||||||
</dl>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="p-3 column is-one-quarter">
|
<div className="">
|
||||||
<dl className="box">
|
{!isUndefined(props.stats.statistics) &&
|
||||||
<dd className="is-size-6">
|
!isEmpty(props.stats.statistics[0].fileTypes) &&
|
||||||
<span className="has-text-weight-bold"></span> Issues
|
map(props.stats.statistics[0].fileTypes, (fileType, idx) => {
|
||||||
</dd>
|
return (
|
||||||
<dd className="is-size-6">
|
<span
|
||||||
<span className="has-text-weight-bold">304</span> Volumes
|
key={idx}
|
||||||
</dd>
|
className="flex flex-col mb-4 h-fit text-xl rounded-lg bg-green-100 dark:bg-green-200 px-4 py-3 text-center"
|
||||||
<dd className="is-size-6">
|
>
|
||||||
{!isUndefined(props.stats.statistics) &&
|
{fileType.data.length} {fileType._id}
|
||||||
!isEmpty(props.stats.statistics[0].fileTypes) &&
|
</span>
|
||||||
map(props.stats.statistics[0].fileTypes, (fileType, idx) => {
|
);
|
||||||
return (
|
})}
|
||||||
<span key={idx}>
|
</div>
|
||||||
<span className="has-text-weight-bold">
|
|
||||||
{fileType.data.length}
|
|
||||||
</span>
|
|
||||||
<span className="tag is-warning has-text-weight-bold mr-2 ml-1">
|
|
||||||
{fileType._id}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* file types */}
|
{/* file types */}
|
||||||
<div className="p-3 column is-two-fifths">
|
<div className="flex flex-col h-fit text-lg rounded-lg bg-green-100 dark:bg-green-200 px-4 py-3">
|
||||||
{/* publisher with most issues */}
|
{/* publisher with most issues */}
|
||||||
<dl className="box">
|
|
||||||
{!isUndefined(props.stats.statistics) &&
|
{!isUndefined(props.stats.statistics) &&
|
||||||
!isEmpty(
|
!isEmpty(
|
||||||
props.stats.statistics[0].publisherWithMostComicsInLibrary[0],
|
props.stats.statistics[0].publisherWithMostComicsInLibrary[0],
|
||||||
) && (
|
) && (
|
||||||
<dd className="is-size-6">
|
<>
|
||||||
<span className="has-text-weight-bold">
|
<span className="">
|
||||||
{
|
{
|
||||||
props.stats.statistics[0]
|
props.stats.statistics[0]
|
||||||
.publisherWithMostComicsInLibrary[0]._id
|
.publisherWithMostComicsInLibrary[0]._id
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
{" has the most issues "}
|
{" has the most issues "}
|
||||||
<span className="has-text-weight-bold">
|
<span className="">
|
||||||
{
|
{
|
||||||
props.stats.statistics[0]
|
props.stats.statistics[0]
|
||||||
.publisherWithMostComicsInLibrary[0].count
|
.publisherWithMostComicsInLibrary[0].count
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</dd>
|
</>
|
||||||
)}
|
)}
|
||||||
<dd className="is-size-6">
|
</div>
|
||||||
<span className="has-text-weight-bold">304</span> Volumes
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -82,7 +82,17 @@ export const PullList = (): ReactElement => {
|
|||||||
<div className="content">
|
<div className="content">
|
||||||
<Header
|
<Header
|
||||||
headerContent="Discover"
|
headerContent="Discover"
|
||||||
subHeaderContent="Pull List aggregated for the week from League Of Comic Geeks"
|
subHeaderContent={
|
||||||
|
<span className="text-md">
|
||||||
|
Pull List aggregated for the week from{" "}
|
||||||
|
<span className="underline">
|
||||||
|
<a href="https://leagueofcomicgeeks.com/comics/new-comics">
|
||||||
|
League Of Comic Geeks
|
||||||
|
</a>
|
||||||
|
<i className="icon-[solar--arrow-right-up-outline] w-4 h-4" />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
iconClassNames="fa-solid fa-binoculars mr-2"
|
iconClassNames="fa-solid fa-binoculars mr-2"
|
||||||
link="/pull-list/all/"
|
link="/pull-list/all/"
|
||||||
/>
|
/>
|
||||||
@@ -101,7 +111,10 @@ export const PullList = (): ReactElement => {
|
|||||||
/>
|
/>
|
||||||
{inputValue && (
|
{inputValue && (
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
Showing pull list for <span>{inputValue}</span>
|
Showing pull list for{" "}
|
||||||
|
<span className="inline-flex mb-2 items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-1 rounded-md dark:text-slate-900 dark:bg-slate-400">
|
||||||
|
{inputValue}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { Form, Field } from "react-final-form";
|
||||||
|
import { PROWLARR_SERVICE_BASE_URI } from "../../../constants/endpoints";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export const ProwlarrSettingsForm = (props) => {
|
||||||
|
const { data } = useQuery({
|
||||||
|
queryFn: async (): any => {
|
||||||
|
return await axios({
|
||||||
|
url: `${PROWLARR_SERVICE_BASE_URI}/getIndexers`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
host: "localhost",
|
||||||
|
port: "9696",
|
||||||
|
apiKey: "c4f42e265fb044dc81f7e88bd41c3367",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
queryKey: ["prowlarrConnectionResult"],
|
||||||
|
});
|
||||||
|
console.log(data);
|
||||||
|
const submitHandler = () => {};
|
||||||
|
const initialData = {};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
Prowlarr Settings.
|
||||||
|
<Form
|
||||||
|
onSubmit={submitHandler}
|
||||||
|
initialValues={initialData}
|
||||||
|
render={({ handleSubmit }) => (
|
||||||
|
<form>
|
||||||
|
<article
|
||||||
|
role="alert"
|
||||||
|
className="mt-4 rounded-lg max-w-screen-md border-s-4 border-blue-500 bg-blue-50 p-4 dark:border-s-4 dark:border-blue-600 dark:bg-blue-300 dark:text-slate-600"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>Configure Prowlarr integration here.</p>
|
||||||
|
<p>
|
||||||
|
Note that you need a Prowlarr instance hosted and running to
|
||||||
|
configure the integration.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
See{" "}
|
||||||
|
<a
|
||||||
|
className="underline"
|
||||||
|
href="http://airdcpp.net/docs/installation/installation.html"
|
||||||
|
>
|
||||||
|
here
|
||||||
|
</a>{" "}
|
||||||
|
for Prowlarr installation instructions for various platforms.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProwlarrSettingsForm;
|
||||||
@@ -3,6 +3,7 @@ import { AirDCPPSettingsForm } from "./AirDCPPSettings/AirDCPPSettingsForm";
|
|||||||
import { AirDCPPHubsForm } from "./AirDCPPSettings/AirDCPPHubsForm";
|
import { AirDCPPHubsForm } from "./AirDCPPSettings/AirDCPPHubsForm";
|
||||||
import { QbittorrentConnectionForm } from "./QbittorrentSettings/QbittorrentConnectionForm";
|
import { QbittorrentConnectionForm } from "./QbittorrentSettings/QbittorrentConnectionForm";
|
||||||
import { SystemSettingsForm } from "./SystemSettings/SystemSettingsForm";
|
import { SystemSettingsForm } from "./SystemSettings/SystemSettingsForm";
|
||||||
|
import ProwlarrSettingsForm from "./ProwlarrSettings/ProwlarrSettingsForm";
|
||||||
import { ServiceStatuses } from "../ServiceStatuses/ServiceStatuses";
|
import { ServiceStatuses } from "../ServiceStatuses/ServiceStatuses";
|
||||||
import settingsObject from "../../constants/settings/settingsMenu.json";
|
import settingsObject from "../../constants/settings/settingsMenu.json";
|
||||||
import { isUndefined, map } from "lodash";
|
import { isUndefined, map } from "lodash";
|
||||||
@@ -37,6 +38,14 @@ export const Settings = (props: ISettingsProps): ReactElement => {
|
|||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "prwlr-connection",
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<ProwlarrSettingsForm />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "core-service",
|
id: "core-service",
|
||||||
content: <>a</>,
|
content: <>a</>,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
|
|||||||
|
|
||||||
type IHeaderProps = {
|
type IHeaderProps = {
|
||||||
headerContent: string;
|
headerContent: string;
|
||||||
subHeaderContent: string;
|
subHeaderContent: ReactElement;
|
||||||
iconClassNames: string;
|
iconClassNames: string;
|
||||||
link?: string;
|
link?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -90,3 +90,10 @@ export const QBITTORRENT_SERVICE_BASE_URI = hostURIBuilder({
|
|||||||
port: "3060",
|
port: "3060",
|
||||||
apiPath: `/api/qbittorrent`,
|
apiPath: `/api/qbittorrent`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const PROWLARR_SERVICE_BASE_URI = hostURIBuilder({
|
||||||
|
protocol: "http",
|
||||||
|
host: import.meta.env.UNDERLYING_HOSTNAME || "localhost",
|
||||||
|
port: "3060",
|
||||||
|
apiPath: `/api/prowlarr`,
|
||||||
|
});
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
"displayName": "Prowlarr",
|
"displayName": "Prowlarr",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "prowlarr-connection",
|
"id": "prwlr-connection",
|
||||||
"displayName": "Connection"
|
"displayName": "Connection"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { ErrorPage } from "./components/shared/ErrorPage";
|
|||||||
const rootEl = document.getElementById("root");
|
const rootEl = document.getElementById("root");
|
||||||
const root = createRoot(rootEl);
|
const root = createRoot(rootEl);
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
||||||
import Import from "./components/Import/Import";
|
import Import from "./components/Import/Import";
|
||||||
import Dashboard from "./components/Dashboard/Dashboard";
|
import Dashboard from "./components/Dashboard/Dashboard";
|
||||||
import Search from "./components/Search/Search";
|
import Search from "./components/Search/Search";
|
||||||
@@ -47,6 +46,5 @@ const router = createBrowserRouter([
|
|||||||
root.render(
|
root.render(
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
<ReactQueryDevtools initialIsOpen={true} />
|
|
||||||
</QueryClientProvider>,
|
</QueryClientProvider>,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user