mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
Feature: Download client rules (#18)
* feat(web): add and update download client rules * feat: add and update download client rules * feat: add active downloads check * chore: update pkg * feat: deluge max active downloads * feat: use basic rules for deluge * feat: add as paused * refactor: download file if needed * feat: better errors qbit
This commit is contained in:
parent
09eb0b1716
commit
c02f16b64d
25 changed files with 628 additions and 228 deletions
|
@ -10,7 +10,7 @@ import {
|
|||
import { useToggle } from "../hooks/hooks";
|
||||
import { useMutation } from "react-query";
|
||||
import { Field, Form } from "react-final-form";
|
||||
import { TextField } from "./inputs";
|
||||
import { SwitchGroup, TextField } from "./inputs";
|
||||
import { NumberField, SelectField } from "./inputs/compact";
|
||||
import DEBUG from "./debug";
|
||||
import APIClient from "../api/APIClient";
|
||||
|
@ -281,6 +281,12 @@ function ListItem({ action, clients, filterID, idx }: ListItemProps) {
|
|||
label="Limit upload speed (KB/s)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||
<div className="col-span-6">
|
||||
<SwitchGroup name="paused" label="Add paused" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case "DELUGE_V1":
|
||||
|
@ -313,6 +319,12 @@ function ListItem({ action, clients, filterID, idx }: ListItemProps) {
|
|||
label="Limit upload speed (KB/s)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||
<div className="col-span-6">
|
||||
<SwitchGroup name="paused" label="Add paused" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case "RADARR":
|
||||
|
|
|
@ -6,6 +6,7 @@ import { classNames } from "../../../styles/utils";
|
|||
interface Props {
|
||||
name: string;
|
||||
label?: string;
|
||||
help?: string;
|
||||
placeholder?: string;
|
||||
defaultValue?: number;
|
||||
className?: string;
|
||||
|
@ -17,6 +18,7 @@ const NumberFieldWide: React.FC<Props> = ({
|
|||
name,
|
||||
label,
|
||||
placeholder,
|
||||
help,
|
||||
defaultValue,
|
||||
required,
|
||||
hidden,
|
||||
|
@ -51,6 +53,9 @@ const NumberFieldWide: React.FC<Props> = ({
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
{help && (
|
||||
<p className="mt-2 text-sm text-gray-500" id={`${name}-description`}>{help}</p>
|
||||
)}
|
||||
<Error name={name} classNames="block text-red-500 mt-2" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Field, Form } from "react-final-form";
|
|||
import DEBUG from "../../components/debug";
|
||||
import APIClient from "../../api/APIClient";
|
||||
import { ActionTypeOptions } from "../../domain/constants";
|
||||
import { TextFieldWide } from "../../components/inputs";
|
||||
import { SwitchGroup, TextFieldWide } from "../../components/inputs";
|
||||
import { AlertWarning } from "../../components/alerts";
|
||||
import {
|
||||
NumberFieldWide,
|
||||
|
@ -206,6 +206,10 @@ function FilterActionAddForm({ filter, isOpen, toggle, clients }: props) {
|
|||
/>
|
||||
<TextFieldWide name="save_path" label="Save path" />
|
||||
|
||||
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
||||
<SwitchGroup name="paused" label="Add paused" />
|
||||
</div>
|
||||
|
||||
<div className="divide-y divide-gray-200 pt-8 space-y-6 sm:pt-10 sm:space-y-5">
|
||||
<div className="px-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||
|
@ -240,6 +244,10 @@ function FilterActionAddForm({ filter, isOpen, toggle, clients }: props) {
|
|||
<TextFieldWide name="label" label="Label" />
|
||||
<TextFieldWide name="save_path" label="Save path" />
|
||||
|
||||
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
||||
<SwitchGroup name="paused" label="Add paused" />
|
||||
</div>
|
||||
|
||||
<div className="divide-y divide-gray-200 pt-8 space-y-6 sm:pt-10 sm:space-y-5">
|
||||
<div className="px-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||
|
|
|
@ -10,7 +10,7 @@ import DEBUG from "../../components/debug";
|
|||
import APIClient from "../../api/APIClient";
|
||||
import { ActionTypeOptions } from "../../domain/constants";
|
||||
import { AlertWarning } from "../../components/alerts";
|
||||
import { TextFieldWide } from "../../components/inputs";
|
||||
import { SwitchGroup, TextFieldWide } from "../../components/inputs";
|
||||
import {
|
||||
NumberFieldWide,
|
||||
RadioFieldsetWide,
|
||||
|
@ -133,6 +133,9 @@ function FilterActionUpdateForm({
|
|||
label="Limit upload speed"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<SwitchGroup name="paused" label="Add paused" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case "DELUGE_V1":
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useState } from "react";
|
||||
import { Fragment, useState } from "react";
|
||||
import { useMutation } from "react-query";
|
||||
import {
|
||||
DOWNLOAD_CLIENT_TYPES,
|
||||
|
@ -15,7 +15,7 @@ import APIClient from "../../../api/APIClient";
|
|||
import { sleep } from "../../../utils/utils";
|
||||
import { DownloadClientTypeOptions } from "../../../domain/constants";
|
||||
import { RadioFieldsetWide } from "../../../components/inputs/wide";
|
||||
import { componentMap } from "./shared";
|
||||
import { componentMap, rulesComponentMap } from "./shared";
|
||||
|
||||
import { toast } from 'react-hot-toast'
|
||||
import Toast from '../../../components/notifications/Toast';
|
||||
|
@ -164,6 +164,8 @@ function DownloadClientAddForm({ isOpen, toggle }: any) {
|
|||
<div>{componentMap[values.type]}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{rulesComponentMap[values.type]}
|
||||
|
||||
<div className="flex-shrink-0 px-4 border-t border-gray-200 py-5 sm:px-6">
|
||||
<div className="space-x-3 flex justify-end">
|
||||
|
|
|
@ -12,7 +12,7 @@ import { SwitchGroup, TextFieldWide } from "../../../components/inputs";
|
|||
import { DownloadClientTypeOptions } from "../../../domain/constants";
|
||||
import APIClient from "../../../api/APIClient";
|
||||
import { sleep } from "../../../utils/utils";
|
||||
import { componentMap } from "./shared";
|
||||
import { componentMap, rulesComponentMap } from "./shared";
|
||||
import { RadioFieldsetWide } from "../../../components/inputs/wide";
|
||||
import { DeleteModal } from "../../../components/modals";
|
||||
|
||||
|
@ -190,6 +190,8 @@ function DownloadClientUpdateForm({ client, isOpen, toggle }: any) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{rulesComponentMap[values.type]}
|
||||
|
||||
<div className="flex-shrink-0 px-4 border-t border-gray-200 py-5 sm:px-6">
|
||||
<div className="space-x-3 flex justify-between">
|
||||
<button
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Fragment } from "react";
|
|||
import { SwitchGroup, TextFieldWide } from "../../../components/inputs";
|
||||
import { NumberFieldWide, PasswordFieldWide } from "../../../components/inputs/wide";
|
||||
import { useField } from "react-final-form";
|
||||
import { Dialog } from "@headlessui/react";
|
||||
|
||||
function FormFieldsDefault() {
|
||||
return (
|
||||
|
@ -50,3 +51,72 @@ export const componentMap: any = {
|
|||
SONARR: <FormFieldsArr />,
|
||||
LIDARR: <FormFieldsArr />,
|
||||
};
|
||||
|
||||
|
||||
function FormFieldsRulesBasic() {
|
||||
const { input: enabled } = useField("settings.rules.enabled");
|
||||
|
||||
return (
|
||||
<div className="border-t border-gray-200 py-5">
|
||||
|
||||
<div className="px-6 space-y-1">
|
||||
<Dialog.Title className="text-lg font-medium text-gray-900">Rules</Dialog.Title>
|
||||
<p className="text-sm text-gray-500">
|
||||
Manage max downloads.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
||||
<SwitchGroup name="settings.rules.enabled" label="Enabled" />
|
||||
</div>
|
||||
|
||||
{enabled.value === true && (
|
||||
<Fragment>
|
||||
<NumberFieldWide name="settings.rules.max_active_downloads" label="Max active downloads" />
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FormFieldsRules() {
|
||||
const { input } = useField("settings.rules.ignore_slow_torrents");
|
||||
const { input: enabled } = useField("settings.rules.enabled");
|
||||
|
||||
return (
|
||||
<div className="border-t border-gray-200 py-5">
|
||||
|
||||
<div className="px-6 space-y-1">
|
||||
<Dialog.Title className="text-lg font-medium text-gray-900">Rules</Dialog.Title>
|
||||
<p className="text-sm text-gray-500">
|
||||
Manage max downloads etc.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
||||
<SwitchGroup name="settings.rules.enabled" label="Enabled" />
|
||||
</div>
|
||||
|
||||
{enabled.value === true && (
|
||||
<Fragment>
|
||||
<NumberFieldWide name="settings.rules.max_active_downloads" label="Max active downloads" />
|
||||
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
||||
<SwitchGroup name="settings.rules.ignore_slow_torrents" label="Ignore slow torrents" />
|
||||
</div>
|
||||
|
||||
{input.value === true && (
|
||||
<Fragment>
|
||||
<NumberFieldWide name="settings.rules.download_speed_threshold" label="Download speed threshold" placeholder="in KB/s" help="If download speed is below this when max active downloads is hit, download anyways. KB/s" />
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const rulesComponentMap: any = {
|
||||
DELUGE_V1: <FormFieldsRulesBasic />,
|
||||
DELUGE_V2: <FormFieldsRulesBasic />,
|
||||
QBITTORRENT: <FormFieldsRules />,
|
||||
};
|
|
@ -42,7 +42,7 @@ function DownloadClientSettingsListItem({ client, idx }: DownloadLClientSettings
|
|||
</Switch>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{client.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{client.host}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{client.host}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{DownloadClientTypeNameMap[client.type]}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<span className="text-indigo-600 hover:text-indigo-900 cursor-pointer" onClick={toggleUpdateClient}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue