mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 16:59:12 +00:00
fix(web): tooltips (#1154)
* fix broken tooltips, replace react-tooltip with react-popper-tooltip * make tooltips use ExternalLink component * fix import * get rid of unused import * fix(tooltip): set delayHide * removed unecessary comment * fix tooltip on mobile * stop tooltip label propagation (mainly for mobile devices) * added onClick convenience prop for label component wrapper (since onClick isn't propagated down) --------- Co-authored-by: soup <soup@r4tio.dev>
This commit is contained in:
parent
98df0c9040
commit
3e3454724b
32 changed files with 1171 additions and 396 deletions
|
@ -69,7 +69,6 @@
|
||||||
"react-select": "^5.7.4",
|
"react-select": "^5.7.4",
|
||||||
"react-table": "^7.8.0",
|
"react-table": "^7.8.0",
|
||||||
"react-textarea-autosize": "^8.5.3",
|
"react-textarea-autosize": "^8.5.3",
|
||||||
"react-tooltip": "^5.21.1",
|
|
||||||
"stacktracey": "^2.1.8",
|
"stacktracey": "^2.1.8",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
|
|
21
web/pnpm-lock.yaml
generated
21
web/pnpm-lock.yaml
generated
|
@ -128,9 +128,6 @@ dependencies:
|
||||||
react-textarea-autosize:
|
react-textarea-autosize:
|
||||||
specifier: ^8.5.3
|
specifier: ^8.5.3
|
||||||
version: 8.5.3(@types/react@18.2.21)(react@18.2.0)
|
version: 8.5.3(@types/react@18.2.21)(react@18.2.0)
|
||||||
react-tooltip:
|
|
||||||
specifier: ^5.21.1
|
|
||||||
version: 5.21.1(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
stacktracey:
|
stacktracey:
|
||||||
specifier: ^2.1.8
|
specifier: ^2.1.8
|
||||||
version: 2.1.8
|
version: 2.1.8
|
||||||
|
@ -2873,10 +2870,6 @@ packages:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/classnames@2.3.2:
|
|
||||||
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/client-only@0.0.1:
|
/client-only@0.0.1:
|
||||||
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
|
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -4763,7 +4756,7 @@ packages:
|
||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
react-dom: '>=16.6.0'
|
react-dom: '>=16.6.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.22.10
|
'@babel/runtime': 7.22.11
|
||||||
'@popperjs/core': 2.11.8
|
'@popperjs/core': 2.11.8
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
@ -4869,18 +4862,6 @@ packages:
|
||||||
- '@types/react'
|
- '@types/react'
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/react-tooltip@5.21.1(react-dom@18.2.0)(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-wJqF/yzK1wuJuy5/zAkVErFA609fVv1ZukhGjw44PcMvg9wL0jomnpQyz3qH1H7TWjz/wqO/OMc3ipQNjZ8zYg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^18.2.0
|
|
||||||
react-dom: '>=16.14.0'
|
|
||||||
dependencies:
|
|
||||||
'@floating-ui/dom': 1.5.1
|
|
||||||
classnames: 2.3.2
|
|
||||||
react: 18.2.0
|
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react-transition-group@4.4.5(react-dom@18.2.0)(react@18.2.0):
|
/react-transition-group@4.4.5(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
|
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
20
web/src/components/ExternalLink.tsx
Normal file
20
web/src/components/ExternalLink.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
type ExternalLinkProps = {
|
||||||
|
href: string;
|
||||||
|
className?: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ExternalLink = ({ href, className, children }: ExternalLinkProps) => (
|
||||||
|
<a
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
href={href}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const DocsLink = ({ href }: { href: string; }) => (
|
||||||
|
<ExternalLink href={href} className="text-blue-400 visited:text-blue-400">{href}</ExternalLink>
|
||||||
|
);
|
|
@ -6,6 +6,7 @@
|
||||||
import StackTracey from "stacktracey";
|
import StackTracey from "stacktracey";
|
||||||
import type { FallbackProps } from "react-error-boundary";
|
import type { FallbackProps } from "react-error-boundary";
|
||||||
import { ArrowPathIcon } from "@heroicons/react/24/solid";
|
import { ArrowPathIcon } from "@heroicons/react/24/solid";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export const ErrorPage = ({ error, resetErrorBoundary }: FallbackProps) => {
|
export const ErrorPage = ({ error, resetErrorBoundary }: FallbackProps) => {
|
||||||
const stack = new StackTracey(error);
|
const stack = new StackTracey(error);
|
||||||
|
@ -35,23 +36,19 @@ export const ErrorPage = ({ error, resetErrorBoundary }: FallbackProps) => {
|
||||||
<h3 className="text-xl leading-6 text-gray-700 dark:text-gray-400 mb-4">
|
<h3 className="text-xl leading-6 text-gray-700 dark:text-gray-400 mb-4">
|
||||||
Please consider reporting this error to our
|
Please consider reporting this error to our
|
||||||
{" "}
|
{" "}
|
||||||
<a
|
<ExternalLink
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href="https://github.com/autobrr/autobrr"
|
href="https://github.com/autobrr/autobrr"
|
||||||
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-sky-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-sky-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
||||||
>
|
>
|
||||||
GitHub page
|
GitHub page
|
||||||
</a>
|
</ExternalLink>
|
||||||
{" or to "}
|
{" or to "}
|
||||||
<a
|
<ExternalLink
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href="https://discord.gg/WQ2eUycxyT"
|
href="https://discord.gg/WQ2eUycxyT"
|
||||||
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-purple-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-purple-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
||||||
>
|
>
|
||||||
our official Discord channel
|
our official Discord channel
|
||||||
</a>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { ReactComponent as Logo } from "@app/logo.svg";
|
import { ReactComponent as Logo } from "@app/logo.svg";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export const NotFound = () => {
|
export const NotFound = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -21,23 +22,19 @@ export const NotFound = () => {
|
||||||
<h3 className="text-xl text-center text-gray-700 dark:text-gray-400 mb-1 px-2">
|
<h3 className="text-xl text-center text-gray-700 dark:text-gray-400 mb-1 px-2">
|
||||||
feel free to report this to our
|
feel free to report this to our
|
||||||
{" "}
|
{" "}
|
||||||
<a
|
<ExternalLink
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href="https://github.com/autobrr/autobrr"
|
href="https://github.com/autobrr/autobrr"
|
||||||
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-sky-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-sky-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
||||||
>
|
>
|
||||||
GitHub page
|
GitHub page
|
||||||
</a>
|
</ExternalLink>
|
||||||
{" or to "}
|
{" or to "}
|
||||||
<a
|
<ExternalLink
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href="https://discord.gg/WQ2eUycxyT"
|
href="https://discord.gg/WQ2eUycxyT"
|
||||||
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-purple-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-purple-500 hover:decoration-2 hover:text-black hover:dark:text-gray-100"
|
||||||
>
|
>
|
||||||
our official Discord channel
|
our official Discord channel
|
||||||
</a>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
</h3>
|
</h3>
|
||||||
<h3 className="text-xl text-center leading-6 text-gray-700 dark:text-gray-400 mb-8 px-2">
|
<h3 className="text-xl text-center leading-6 text-gray-700 dark:text-gray-400 mb-8 px-2">
|
||||||
|
|
|
@ -4,18 +4,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { toast } from "react-hot-toast";
|
||||||
import { formatDistanceToNowStrict } from "date-fns";
|
import { formatDistanceToNowStrict } from "date-fns";
|
||||||
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
import { ArrowPathIcon, CheckIcon } from "@heroicons/react/24/solid";
|
import { ArrowPathIcon, CheckIcon } from "@heroicons/react/24/solid";
|
||||||
import { ClockIcon, ExclamationCircleIcon, NoSymbolIcon } from "@heroicons/react/24/outline";
|
import { ClockIcon, ExclamationCircleIcon, NoSymbolIcon } from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
import { classNames, simplifyDate } from "@utils";
|
|
||||||
import { Tooltip } from "@components/tooltips/Tooltip";
|
|
||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
||||||
import { APIClient } from "@api/APIClient";
|
import { APIClient } from "@api/APIClient";
|
||||||
|
import { classNames, simplifyDate } from "@utils";
|
||||||
import { filterKeys } from "@screens/filters/List";
|
import { filterKeys } from "@screens/filters/List";
|
||||||
import { toast } from "react-hot-toast";
|
|
||||||
import Toast from "@components/notifications/Toast";
|
import Toast from "@components/notifications/Toast";
|
||||||
import { RingResizeSpinner } from "@components/Icons";
|
import { RingResizeSpinner } from "@components/Icons";
|
||||||
|
import { Tooltip } from "@components/tooltips/Tooltip";
|
||||||
|
|
||||||
interface CellProps {
|
interface CellProps {
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -35,6 +35,7 @@ export const IndexerCell = ({ value }: CellProps) => (
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
requiresClick
|
||||||
label={value}
|
label={value}
|
||||||
maxWidth="max-w-[90vw]"
|
maxWidth="max-w-[90vw]"
|
||||||
>
|
>
|
||||||
|
@ -53,6 +54,7 @@ export const TitleCell = ({ value }: CellProps) => (
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
requiresClick
|
||||||
label={value}
|
label={value}
|
||||||
maxWidth="max-w-[90vw]"
|
maxWidth="max-w-[90vw]"
|
||||||
>
|
>
|
||||||
|
@ -221,6 +223,7 @@ export const ReleaseStatusCell = ({ value }: ReleaseStatusCellProps) => (
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
requiresClick
|
||||||
label={StatusCellMap[v.status].icon}
|
label={StatusCellMap[v.status].icon}
|
||||||
title={StatusCellMap[v.status].textFormatter(v)}
|
title={StatusCellMap[v.status].textFormatter(v)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -15,6 +15,7 @@ import Toast from "@components/notifications/Toast";
|
||||||
import { LeftNav } from "./LeftNav";
|
import { LeftNav } from "./LeftNav";
|
||||||
import { RightNav } from "./RightNav";
|
import { RightNav } from "./RightNav";
|
||||||
import { MobileNav } from "./MobileNav";
|
import { MobileNav } from "./MobileNav";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export const Header = () => {
|
export const Header = () => {
|
||||||
const { data: config } = useQuery({
|
const { data: config } = useQuery({
|
||||||
|
@ -77,13 +78,13 @@ export const Header = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data?.html_url && (
|
{data?.html_url && (
|
||||||
<a href={data.html_url} target="_blank" rel="noopener noreferrer">
|
<ExternalLink href={data.html_url}>
|
||||||
<div className="flex mt-4 py-2 bg-blue-500 rounded justify-center">
|
<div className="flex mt-4 py-2 bg-blue-500 rounded justify-center">
|
||||||
<MegaphoneIcon className="h-6 w-6 text-blue-100" />
|
<MegaphoneIcon className="h-6 w-6 text-blue-100" />
|
||||||
<span className="text-blue-100 font-medium mx-3">New update available!</span>
|
<span className="text-blue-100 font-medium mx-3">New update available!</span>
|
||||||
<span className="inline-flex items-center rounded-md bg-blue-100 px-2.5 py-0.5 text-sm font-medium text-blue-800">{data?.name}</span>
|
<span className="inline-flex items-center rounded-md bg-blue-100 px-2.5 py-0.5 text-sm font-medium text-blue-800">{data?.name}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</ExternalLink>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { classNames } from "@utils";
|
||||||
import { ReactComponent as Logo } from "@app/logo.svg";
|
import { ReactComponent as Logo } from "@app/logo.svg";
|
||||||
|
|
||||||
import { NAV_ROUTES } from "./_shared";
|
import { NAV_ROUTES } from "./_shared";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export const LeftNav = () => (
|
export const LeftNav = () => (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
@ -38,9 +39,7 @@ export const LeftNav = () => (
|
||||||
{item.name}
|
{item.name}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
<a
|
<ExternalLink
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href="https://autobrr.com"
|
href="https://autobrr.com"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"text-gray-600 dark:text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-2xl text-sm font-medium",
|
"text-gray-600 dark:text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-2xl text-sm font-medium",
|
||||||
|
@ -52,7 +51,7 @@ export const LeftNav = () => (
|
||||||
className="inline ml-1 h-5 w-5"
|
className="inline ml-1 h-5 w-5"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</a>
|
</ExternalLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import { Field, FieldProps } from "formik";
|
import { Field, FieldProps } from "formik";
|
||||||
import { classNames } from "@utils";
|
import { classNames } from "@utils";
|
||||||
import { CustomTooltip } from "@components/tooltips/CustomTooltip";
|
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
|
||||||
|
|
||||||
interface ErrorFieldProps {
|
interface ErrorFieldProps {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -63,10 +63,9 @@ const CheckboxField = ({
|
||||||
<div className="ml-3 text-sm">
|
<div className="ml-3 text-sm">
|
||||||
<label htmlFor={name} className="flex mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
<label htmlFor={name} className="flex mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
) : label}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<p className="text-gray-500">{sublabel}</p>
|
<p className="text-gray-500">{sublabel}</p>
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/
|
||||||
import TextareaAutosize from "react-textarea-autosize";
|
import TextareaAutosize from "react-textarea-autosize";
|
||||||
|
|
||||||
import { useToggle } from "@hooks/hooks";
|
import { useToggle } from "@hooks/hooks";
|
||||||
import { CustomTooltip } from "@components/tooltips/CustomTooltip";
|
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
|
||||||
import { classNames } from "@utils";
|
import { classNames } from "@utils";
|
||||||
|
|
||||||
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||||
|
@ -46,10 +46,9 @@ export const TextField = ({
|
||||||
{label && (
|
{label && (
|
||||||
<label htmlFor={name} className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
<label htmlFor={name} className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
) : label}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
@ -185,8 +184,9 @@ export const RegexField = ({
|
||||||
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
|
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
<span className="z-10">{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}</span>
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
@ -324,9 +324,10 @@ export const RegexTextAreaField = ({
|
||||||
htmlFor={name}
|
htmlFor={name}
|
||||||
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
|
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex z-10">
|
||||||
{label}
|
{tooltip ? (
|
||||||
<span className="z-10">{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}</span>
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
@ -412,10 +413,9 @@ export const TextArea = ({
|
||||||
{label && (
|
{label && (
|
||||||
<label htmlFor={name} className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
<label htmlFor={name} className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
) : label}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
@ -484,10 +484,9 @@ export const TextAreaAutoResize = ({
|
||||||
{label && (
|
{label && (
|
||||||
<label htmlFor={name} className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
<label htmlFor={name} className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
) : label}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
@ -630,8 +629,9 @@ export const NumberField = ({
|
||||||
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
|
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { Switch } from "@headlessui/react";
|
||||||
import { ErrorField, RequiredField } from "./common";
|
import { ErrorField, RequiredField } from "./common";
|
||||||
import Select, { components, ControlProps, InputProps, MenuProps, OptionProps } from "react-select";
|
import Select, { components, ControlProps, InputProps, MenuProps, OptionProps } from "react-select";
|
||||||
import { SelectFieldProps } from "./select";
|
import { SelectFieldProps } from "./select";
|
||||||
import { CustomTooltip } from "@components/tooltips/CustomTooltip";
|
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
|
||||||
|
|
||||||
interface TextFieldWideProps {
|
interface TextFieldWideProps {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -43,7 +43,9 @@ export const TextFieldWide = ({
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor={name} className="flex text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2">
|
<label htmlFor={name} className="flex text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label} {tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
<RequiredField required={required} />
|
<RequiredField required={required} />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
@ -108,7 +110,9 @@ export const PasswordFieldWide = ({
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor={name} className="flex text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2">
|
<label htmlFor={name} className="flex text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label} {tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
<RequiredField required={required} />
|
<RequiredField required={required} />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
@ -172,7 +176,9 @@ export const NumberFieldWide = ({
|
||||||
className="block text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2"
|
className="block text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label} {tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
<RequiredField required={required} />
|
<RequiredField required={required} />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
@ -232,10 +238,11 @@ export const SwitchGroupWide = ({
|
||||||
<ul className="px-4 divide-y divide-gray-200 dark:divide-gray-700">
|
<ul className="px-4 divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
<Switch.Group as="li" className="py-4 flex items-center justify-between">
|
<Switch.Group as="li" className="py-4 flex items-center justify-between">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Switch.Label as="div" className="text-sm font-medium text-gray-900 dark:text-white"
|
<Switch.Label as="div" passive className="text-sm font-medium text-gray-900 dark:text-white">
|
||||||
passive>
|
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label} {tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</Switch.Label>
|
</Switch.Label>
|
||||||
{description && (
|
{description && (
|
||||||
|
@ -396,8 +403,9 @@ export const SelectFieldWide = ({
|
||||||
className="flex text-sm font-medium text-gray-900 dark:text-white"
|
className="flex text-sm font-medium text-gray-900 dark:text-white"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { MultiSelect as RMSC } from "react-multi-select-component";
|
||||||
|
|
||||||
import { classNames, COL_WIDTHS } from "@utils";
|
import { classNames, COL_WIDTHS } from "@utils";
|
||||||
import { SettingsContext } from "@utils/Context";
|
import { SettingsContext } from "@utils/Context";
|
||||||
import { CustomTooltip } from "@components/tooltips/CustomTooltip";
|
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
|
||||||
|
|
||||||
export interface MultiSelectOption {
|
export interface MultiSelectOption {
|
||||||
value: string | number;
|
value: string | number;
|
||||||
|
@ -56,10 +56,9 @@ export const MultiSelect = ({
|
||||||
<label
|
<label
|
||||||
htmlFor={label} className="flex mb-2 text-xs font-bold tracking-wide text-gray-700 uppercase dark:text-gray-200">
|
htmlFor={label} className="flex mb-2 text-xs font-bold tracking-wide text-gray-700 uppercase dark:text-gray-200">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
) : label}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
@ -297,10 +296,9 @@ export const Select = ({
|
||||||
<>
|
<>
|
||||||
<Listbox.Label className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
<Listbox.Label className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{tooltip ? (
|
||||||
{tooltip && (
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
) : label}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</Listbox.Label>
|
</Listbox.Label>
|
||||||
<div className="mt-2 relative">
|
<div className="mt-2 relative">
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { Field } from "formik";
|
||||||
import Select, { components, ControlProps, InputProps, MenuProps, OptionProps } from "react-select";
|
import Select, { components, ControlProps, InputProps, MenuProps, OptionProps } from "react-select";
|
||||||
import { OptionBasicTyped } from "@domain/constants";
|
import { OptionBasicTyped } from "@domain/constants";
|
||||||
import CreatableSelect from "react-select/creatable";
|
import CreatableSelect from "react-select/creatable";
|
||||||
import { CustomTooltip } from "@components/tooltips/CustomTooltip";
|
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
|
||||||
|
|
||||||
interface SelectFieldProps<T> {
|
interface SelectFieldProps<T> {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -29,7 +29,9 @@ export function SelectFieldCreatable<T>({ name, label, help, placeholder, toolti
|
||||||
className="block text-sm font-medium text-gray-900 dark:text-white sm:pt-2"
|
className="block text-sm font-medium text-gray-900 dark:text-white sm:pt-2"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label} {tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -200,7 +202,9 @@ export function SelectFieldBasic<T>({ name, label, help, placeholder, tooltip, d
|
||||||
className="block text-sm font-medium text-gray-900 dark:text-white sm:pt-2"
|
className="block text-sm font-medium text-gray-900 dark:text-white sm:pt-2"
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label} {tooltip && (<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>)}
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Field } from "formik";
|
||||||
import { Switch as HeadlessSwitch } from "@headlessui/react";
|
import { Switch as HeadlessSwitch } from "@headlessui/react";
|
||||||
|
|
||||||
import { classNames } from "@utils";
|
import { classNames } from "@utils";
|
||||||
import { CustomTooltip } from "@components/tooltips/CustomTooltip";
|
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
|
||||||
|
|
||||||
type SwitchProps<V = unknown> = {
|
type SwitchProps<V = unknown> = {
|
||||||
label?: string
|
label?: string
|
||||||
|
@ -88,13 +88,18 @@ const SwitchGroup = ({
|
||||||
}: SwitchGroupProps) => (
|
}: SwitchGroupProps) => (
|
||||||
<HeadlessSwitch.Group as="ol" className="py-4 flex items-center justify-between">
|
<HeadlessSwitch.Group as="ol" className="py-4 flex items-center justify-between">
|
||||||
{label && <div className="flex flex-col">
|
{label && <div className="flex flex-col">
|
||||||
<HeadlessSwitch.Label as={heading ? "h2" : "span"} className={classNames("flex float-left cursor-default mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide", heading ? "text-lg" : "text-sm")}
|
<HeadlessSwitch.Label
|
||||||
passive>
|
passive
|
||||||
<div className="flex">
|
as={heading ? "h2" : "span"}
|
||||||
{label}
|
className={classNames(
|
||||||
{tooltip && (
|
"flex float-left cursor-default mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide",
|
||||||
<CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>
|
heading ? "text-lg" : "text-sm"
|
||||||
)}
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex">
|
||||||
|
{tooltip ? (
|
||||||
|
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
|
||||||
|
) : label}
|
||||||
</div>
|
</div>
|
||||||
</HeadlessSwitch.Label>
|
</HeadlessSwitch.Label>
|
||||||
{description && (
|
{description && (
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors.
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
.react-tooltip code {
|
|
||||||
background-color: rgb(63, 71, 94);
|
|
||||||
padding-left: 4px;
|
|
||||||
padding-right: 4px;
|
|
||||||
padding-top: 2px;
|
|
||||||
padding-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-tooltip a:hover {
|
|
||||||
text-decoration-line: underline;
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors.
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { PlacesType, Tooltip } from "react-tooltip";
|
|
||||||
import "./CustomTooltip.css";
|
|
||||||
|
|
||||||
|
|
||||||
interface CustomTooltipProps {
|
|
||||||
anchorId: string;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
clickable?: boolean;
|
|
||||||
place?: PlacesType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CustomTooltip = ({
|
|
||||||
anchorId,
|
|
||||||
children,
|
|
||||||
clickable = true,
|
|
||||||
place = "top"
|
|
||||||
}: CustomTooltipProps) => {
|
|
||||||
const id = `${anchorId}-tooltip`;
|
|
||||||
return (
|
|
||||||
<div className="flex items-center">
|
|
||||||
<svg id={id} className="ml-1 w-4 h-4 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
|
|
||||||
<Tooltip
|
|
||||||
style={{ maxWidth: "350px", fontSize: "12px", textTransform: "none", fontWeight: "normal", borderRadius: "0.375rem", backgroundColor: "#34343A", color: "#fff" }}
|
|
||||||
delayShow={100}
|
|
||||||
delayHide={150}
|
|
||||||
place={place}
|
|
||||||
anchorSelect={id}
|
|
||||||
data-html={true}
|
|
||||||
clickable={clickable}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
25
web/src/components/tooltips/DocsTooltip.tsx
Normal file
25
web/src/components/tooltips/DocsTooltip.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors.
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Tooltip } from "./Tooltip";
|
||||||
|
|
||||||
|
interface DocsTooltipProps {
|
||||||
|
label?: React.ReactNode;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DocsTooltip = ({ label, children }: DocsTooltipProps) => (
|
||||||
|
<Tooltip
|
||||||
|
label={
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
{label ?? null}
|
||||||
|
<svg className="ml-1 w-4 h-4 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10" /></svg>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
|
@ -3,22 +3,30 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
import { Transition } from "@headlessui/react";
|
||||||
import { usePopperTooltip } from "react-popper-tooltip";
|
import { usePopperTooltip } from "react-popper-tooltip";
|
||||||
|
|
||||||
import { classNames } from "@utils";
|
import { classNames } from "@utils";
|
||||||
|
|
||||||
interface TooltipProps {
|
interface TooltipProps {
|
||||||
label: ReactNode;
|
label: ReactNode;
|
||||||
|
onLabelClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
title?: ReactNode;
|
title?: ReactNode;
|
||||||
maxWidth?: string;
|
maxWidth?: string;
|
||||||
|
requiresClick?: boolean;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE(stacksmash76): onClick is not propagated
|
||||||
|
// to the label (always-visible) component, so you will have
|
||||||
|
// to use the `onLabelClick` prop in this case.
|
||||||
export const Tooltip = ({
|
export const Tooltip = ({
|
||||||
label,
|
label,
|
||||||
|
onLabelClick,
|
||||||
title,
|
title,
|
||||||
children,
|
children,
|
||||||
|
requiresClick,
|
||||||
maxWidth = "max-w-sm"
|
maxWidth = "max-w-sm"
|
||||||
}: TooltipProps) => {
|
}: TooltipProps) => {
|
||||||
const {
|
const {
|
||||||
|
@ -28,22 +36,46 @@ export const Tooltip = ({
|
||||||
setTriggerRef,
|
setTriggerRef,
|
||||||
visible
|
visible
|
||||||
} = usePopperTooltip({
|
} = usePopperTooltip({
|
||||||
trigger: ["click"],
|
trigger: requiresClick ? ["click"] : ["click", "hover"],
|
||||||
interactive: false
|
interactive: !requiresClick,
|
||||||
|
delayHide: 200
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!children || Array.isArray(children) && !children.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div ref={setTriggerRef} className="truncate">
|
<div
|
||||||
|
ref={setTriggerRef}
|
||||||
|
className="truncate"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
|
|
||||||
|
onLabelClick?.(e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
{visible && (
|
<Transition
|
||||||
|
show={visible}
|
||||||
|
className="z-10"
|
||||||
|
enter="transition duration-200 ease-out"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="transition duration-200 ease-in"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
ref={setTooltipRef}
|
ref={setTooltipRef}
|
||||||
{...getTooltipProps({
|
{...getTooltipProps({
|
||||||
className: classNames(
|
className: classNames(
|
||||||
maxWidth,
|
maxWidth,
|
||||||
"rounded-md border border-gray-300 text-black text-xs shadow-lg dark:text-white dark:border-gray-700 dark:shadow-2xl"
|
"rounded-md border border-gray-300 text-black text-xs normal-case tracking-normal font-normal shadow-lg dark:text-white dark:border-gray-700 dark:shadow-2xl"
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -55,13 +87,13 @@ export const Tooltip = ({
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
title ? "" : "rounded-t-md",
|
title ? "" : "rounded-t-md",
|
||||||
"py-1 px-2 rounded-b-md bg-white dark:bg-gray-900"
|
"whitespace-normal break-words py-1 px-2 rounded-b-md bg-white dark:bg-gray-900"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</Transition>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
|
@ -26,6 +26,7 @@ import {
|
||||||
} from "@components/inputs";
|
} from "@components/inputs";
|
||||||
import { clientKeys } from "@screens/settings/DownloadClient";
|
import { clientKeys } from "@screens/settings/DownloadClient";
|
||||||
import { SelectFieldWide } from "@components/inputs/input_wide";
|
import { SelectFieldWide } from "@components/inputs/input_wide";
|
||||||
|
import { DocsLink, ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
interface InitialValuesSettings {
|
interface InitialValuesSettings {
|
||||||
basic?: {
|
basic?: {
|
||||||
|
@ -54,7 +55,6 @@ interface InitialValues {
|
||||||
settings: InitialValuesSettings;
|
settings: InitialValuesSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function FormFieldsDeluge() {
|
function FormFieldsDeluge() {
|
||||||
const {
|
const {
|
||||||
values: { tls }
|
values: { tls }
|
||||||
|
@ -63,11 +63,20 @@ function FormFieldsDeluge() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide
|
<TextFieldWide
|
||||||
|
required
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd:port"
|
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd:port"
|
||||||
tooltip={<div><p>See guides for how to connect to Deluge for various server types in our docs.</p><br /><p>Dedicated servers:</p><a href='https://autobrr.com/configuration/download-clients/dedicated#deluge' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#deluge</a><p>Shared seedbox providers:</p><a href='https://autobrr.com/configuration/download-clients/shared-seedboxes#deluge' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/shared-seedboxes#deluge</a></div>}
|
tooltip={
|
||||||
required={true}
|
<div>
|
||||||
|
<p>See guides for how to connect to Deluge for various server types in our docs.</p>
|
||||||
|
<br />
|
||||||
|
<p>Dedicated servers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#deluge" />
|
||||||
|
<p>Shared seedbox providers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/shared-seedboxes#deluge" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<NumberFieldWide
|
<NumberFieldWide
|
||||||
|
@ -99,14 +108,23 @@ function FormFieldsArr() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-4 px-1 mb-4 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 mb-4 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide
|
<TextFieldWide
|
||||||
|
required
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Full url http(s)://domain.ltd and/or subdomain/subfolder"
|
help="Full url http(s)://domain.ltd and/or subdomain/subfolder"
|
||||||
tooltip={<div><p>See guides for how to connect to the *arr suite for various server types in our docs.</p><br /><p>Dedicated servers:</p><a href='https://autobrr.com/configuration/download-clients/dedicated/#sonarr' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated/</a><p>Shared seedbox providers:</p><a href='https://autobrr.com/configuration/download-clients/shared-seedboxes#sonarr' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/shared-seedboxes</a></div>}
|
tooltip={
|
||||||
required={true}
|
<div>
|
||||||
|
<p>See guides for how to connect to the *arr suite for various server types in our docs.</p>
|
||||||
|
<br />
|
||||||
|
<p>Dedicated servers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated/#sonarr" />
|
||||||
|
<p>Shared seedbox providers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/shared-seedboxes#sonarr" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PasswordFieldWide name="settings.apikey" label="API key" required={true}/>
|
<PasswordFieldWide required name="settings.apikey" label="API key" />
|
||||||
|
|
||||||
<SwitchGroupWide name="settings.basic.auth" label="Basic auth" />
|
<SwitchGroupWide name="settings.basic.auth" label="Basic auth" />
|
||||||
|
|
||||||
|
@ -130,11 +148,20 @@ function FormFieldsQbit() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide
|
<TextFieldWide
|
||||||
|
required
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Eg. http(s)://client.domain.ltd, http(s)://domain.ltd/qbittorrent, http://domain.ltd:port"
|
help="Eg. http(s)://client.domain.ltd, http(s)://domain.ltd/qbittorrent, http://domain.ltd:port"
|
||||||
tooltip={<div><p>See guides for how to connect to qBittorrent for various server types in our docs.</p><br /><p>Dedicated servers:</p><a href='https://autobrr.com/configuration/download-clients/dedicated#qbittorrent' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#qbittorrent</a><p>Shared seedbox providers:</p><a href='https://autobrr.com/configuration/download-clients/shared-seedboxes#qbittorrent' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/shared-seedboxes#qbittorrent</a></div>}
|
tooltip={
|
||||||
required={true}
|
<div>
|
||||||
|
<p>See guides for how to connect to qBittorrent for various server types in our docs.</p>
|
||||||
|
<br />
|
||||||
|
<p>Dedicated servers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#qbittorrent" />
|
||||||
|
<p>Shared seedbox providers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/shared-seedboxes#qbittorrent" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{port > 0 && (
|
{port > 0 && (
|
||||||
|
@ -177,16 +204,15 @@ function FormFieldsPorla() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide
|
<TextFieldWide
|
||||||
|
required
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Eg. http(s)://client.domain.ltd, http(s)://domain.ltd/porla, http://domain.ltd:port"
|
help="Eg. http(s)://client.domain.ltd, http(s)://domain.ltd/porla, http://domain.ltd:port"
|
||||||
required={true}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
<SwitchGroupWide name="tls" label="TLS" />
|
<SwitchGroupWide name="tls" label="TLS" />
|
||||||
|
|
||||||
<PasswordFieldWide name="settings.apikey" label="Auth token" required={true}/>
|
<PasswordFieldWide required name="settings.apikey" label="Auth token" />
|
||||||
|
|
||||||
{tls && (
|
{tls && (
|
||||||
<SwitchGroupWide
|
<SwitchGroupWide
|
||||||
|
@ -215,11 +241,20 @@ function FormFieldsRTorrent() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide
|
<TextFieldWide
|
||||||
|
required
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Eg. http(s)://client.domain.ltd/RPC2, http(s)://domain.ltd/client, http(s)://domain.ltd/RPC2"
|
help="Eg. http(s)://client.domain.ltd/RPC2, http(s)://domain.ltd/client, http(s)://domain.ltd/RPC2"
|
||||||
tooltip={<div><p>See guides for how to connect to rTorrent for various server types in our docs.</p><br /><p>Dedicated servers:</p><a href='https://autobrr.com/configuration/download-clients/dedicated#rtorrent--rutorrent' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#rtorrent--rutorrent</a><p>Shared seedbox providers:</p><a href='https://autobrr.com/configuration/download-clients/shared-seedboxes#rtorrent' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/shared-seedboxes#rtorrent</a></div>}
|
tooltip={
|
||||||
required={true}
|
<div>
|
||||||
|
<p>See guides for how to connect to rTorrent for various server types in our docs.</p>
|
||||||
|
<br />
|
||||||
|
<p>Dedicated servers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#rtorrent--rutorrent" />
|
||||||
|
<p>Shared seedbox providers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/shared-seedboxes#rtorrent" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SwitchGroupWide name="tls" label="TLS" />
|
<SwitchGroupWide name="tls" label="TLS" />
|
||||||
|
@ -251,11 +286,20 @@ function FormFieldsTransmission() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide
|
<TextFieldWide
|
||||||
|
required
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd"
|
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd"
|
||||||
tooltip={<div><p>See guides for how to connect to Transmission for various server types in our docs.</p><br /><p>Dedicated servers:</p><a href='https://autobrr.com/configuration/download-clients/dedicated#transmission' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#transmission</a><p>Shared seedbox providers:</p><a href='https://autobrr.com/configuration/download-clients/shared-seedboxes#transmisison' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/shared-seedboxes#transmisison</a></div>}
|
tooltip={
|
||||||
required={true}
|
<div>
|
||||||
|
<p>See guides for how to connect to Transmission for various server types in our docs.</p>
|
||||||
|
<br />
|
||||||
|
<p>Dedicated servers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#transmission" />
|
||||||
|
<p>Shared seedbox providers:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/shared-seedboxes#transmisison" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<NumberFieldWide name="port" label="Port" help="Port for Transmission" />
|
<NumberFieldWide name="port" label="Port" help="Port for Transmission" />
|
||||||
|
@ -286,7 +330,16 @@ function FormFieldsSabnzbd() {
|
||||||
name="host"
|
name="host"
|
||||||
label="Host"
|
label="Host"
|
||||||
help="Eg. http://ip:port or https://url.com/sabnzbd"
|
help="Eg. http://ip:port or https://url.com/sabnzbd"
|
||||||
// tooltip={<div><p>See guides for how to connect to qBittorrent for various server types in our docs.</p><br /><p>Dedicated servers:</p><a href='https://autobrr.com/configuration/download-clients/dedicated#qbittorrent' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#qbittorrent</a><p>Shared seedbox providers:</p><a href='https://autobrr.com/configuration/download-clients/shared-seedboxes#qbittorrent' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/shared-seedboxes#qbittorrent</a></div>}
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>See our guides on how to connect to qBittorrent for various server types in our docs.</p>
|
||||||
|
<br />
|
||||||
|
<p>Dedicated servers:</p>
|
||||||
|
<ExternalLink href="https://autobrr.com/configuration/download-clients/dedicated#qbittorrent" />
|
||||||
|
<p>Shared seedbox providers:</p>
|
||||||
|
<ExternalLink href="https://autobrr.com/configuration/download-clients/shared-seedboxes#qbittorrent" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{port > 0 && (
|
{port > 0 && (
|
||||||
|
@ -360,7 +413,19 @@ function FormFieldsRulesBasic() {
|
||||||
<SwitchGroupWide name="settings.rules.enabled" label="Enabled" />
|
<SwitchGroupWide name="settings.rules.enabled" label="Enabled" />
|
||||||
|
|
||||||
{settings && settings.rules?.enabled === true && (
|
{settings && settings.rules?.enabled === true && (
|
||||||
<NumberFieldWide name="settings.rules.max_active_downloads" label="Max active downloads" tooltip={<span><p>Limit the amount of active downloads (0 is unlimited), to give the maximum amount of bandwidth and disk for the downloads.</p><a href='https://autobrr.com/configuration/download-clients/dedicated#deluge-rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#deluge-rules</a><br /><br /><p>See recommendations for various server types here:</p><a href='https://autobrr.com/filters/examples#build-buffer' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/examples#build-buffer</a></span>} />
|
<NumberFieldWide
|
||||||
|
name="settings.rules.max_active_downloads"
|
||||||
|
label="Max active downloads"
|
||||||
|
tooltip={
|
||||||
|
<span>
|
||||||
|
<p>Limit the amount of active downloads (0 is unlimited), to give the maximum amount of bandwidth and disk for the downloads.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#deluge-rules" />
|
||||||
|
<br /><br />
|
||||||
|
<p>See recommendations for various server types here:</p>
|
||||||
|
<DocsLink href='https://autobrr.com/filters/examples#build-buffer' />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -389,7 +454,16 @@ function FormFieldsRulesQbit() {
|
||||||
<NumberFieldWide
|
<NumberFieldWide
|
||||||
name="settings.rules.max_active_downloads"
|
name="settings.rules.max_active_downloads"
|
||||||
label="Max active downloads"
|
label="Max active downloads"
|
||||||
tooltip={<><p>Limit the amount of active downloads (0 is unlimited), to give the maximum amount of bandwidth and disk for the downloads.</p><a href='https://autobrr.com/configuration/download-clients/dedicated#qbittorrent-rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#qbittorrent-rules</a><br /><br /><p>See recommendations for various server types here:</p><a href='https://autobrr.com/filters/examples#build-buffer' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/examples#build-buffer</a></>} />
|
tooltip={
|
||||||
|
<>
|
||||||
|
<p>Limit the amount of active downloads (0 is unlimited), to give the maximum amount of bandwidth and disk for the downloads.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#qbittorrent-rules" />
|
||||||
|
<br /><br />
|
||||||
|
<p>See recommendations for various server types here:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/examples#build-buffer" />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<SwitchGroupWide
|
<SwitchGroupWide
|
||||||
name="settings.rules.ignore_slow_torrents"
|
name="settings.rules.ignore_slow_torrents"
|
||||||
label="Ignore slow torrents"
|
label="Ignore slow torrents"
|
||||||
|
@ -447,7 +521,15 @@ function FormFieldsRulesTransmission() {
|
||||||
<NumberFieldWide
|
<NumberFieldWide
|
||||||
name="settings.rules.max_active_downloads"
|
name="settings.rules.max_active_downloads"
|
||||||
label="Max active downloads"
|
label="Max active downloads"
|
||||||
tooltip={<><p>Limit the amount of active downloads (0 is unlimited), to give the maximum amount of bandwidth and disk for the downloads.</p><a href='https://autobrr.com/configuration/download-clients/dedicated#transmission-rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/download-clients/dedicated#transmission-rules</a><br /><br /><p>See recommendations for various server types here:</p><a href='https://autobrr.com/filters/examples#build-buffer' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/examples#build-buffer</a></>}
|
tooltip={
|
||||||
|
<>
|
||||||
|
<p>Limit the amount of active downloads (0 is unlimited), to give the maximum amount of bandwidth and disk for the downloads.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/download-clients/dedicated#transmission-rules" />
|
||||||
|
<br /><br />
|
||||||
|
<p>See recommendations for various server types here:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/examples#build-buffer" />
|
||||||
|
</>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -697,7 +779,7 @@ export function DownloadClientAddForm({ isOpen, toggle }: formProps) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
|
||||||
<TextFieldWide name="name" label="Name" required={true}/>
|
<TextFieldWide required name="name" label="Name" />
|
||||||
<SwitchGroupWide name="enabled" label="Enabled" />
|
<SwitchGroupWide name="enabled" label="Enabled" />
|
||||||
<RadioFieldsetWide
|
<RadioFieldsetWide
|
||||||
name="type"
|
name="type"
|
||||||
|
@ -892,7 +974,7 @@ export function DownloadClientUpdateForm({ client, isOpen, toggle }: updateFormP
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y dark:divide-gray-700">
|
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y dark:divide-gray-700">
|
||||||
<TextFieldWide name="name" label="Name" required={true}/>
|
<TextFieldWide required name="name" label="Name" />
|
||||||
<SwitchGroupWide name="enabled" label="Enabled" />
|
<SwitchGroupWide name="enabled" label="Enabled" />
|
||||||
<RadioFieldsetWide
|
<RadioFieldsetWide
|
||||||
name="type"
|
name="type"
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { SelectFieldBasic, SelectFieldCreatable } from "@components/inputs/selec
|
||||||
import { FeedDownloadTypeOptions } from "@domain/constants";
|
import { FeedDownloadTypeOptions } from "@domain/constants";
|
||||||
import { feedKeys } from "@screens/settings/Feed";
|
import { feedKeys } from "@screens/settings/Feed";
|
||||||
import { indexerKeys } from "@screens/settings/Indexer";
|
import { indexerKeys } from "@screens/settings/Indexer";
|
||||||
|
import { DocsLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
const Input = (props: InputProps) => (
|
const Input = (props: InputProps) => (
|
||||||
<components.Input
|
<components.Input
|
||||||
|
@ -87,10 +88,26 @@ const IrcSettingFields = (ind: IndexerDefinition, indexer: string) => {
|
||||||
{ind.irc.settings.map((f: IndexerSetting, idx: number) => {
|
{ind.irc.settings.map((f: IndexerSetting, idx: number) => {
|
||||||
switch (f.type) {
|
switch (f.type) {
|
||||||
case "text":
|
case "text":
|
||||||
return <TextFieldWide name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} autoComplete="off" validate={validateField(f)} tooltip={<div><p>Please read our IRC guide if you are unfamiliar with IRC.</p><a href='https://autobrr.com/configuration/irc' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/configuration/irc</a></div>} />;
|
return (
|
||||||
|
<TextFieldWide
|
||||||
|
key={idx}
|
||||||
|
name={`irc.${f.name}`}
|
||||||
|
label={f.label}
|
||||||
|
required={f.required}
|
||||||
|
help={f.help}
|
||||||
|
autoComplete="off"
|
||||||
|
validate={validateField(f)}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Please read our IRC guide if you are unfamiliar with IRC.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/configuration/irc" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "secret":
|
case "secret":
|
||||||
if (f.name === "invite_command") {
|
if (f.name === "invite_command") {
|
||||||
return <PasswordFieldWide name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} defaultVisible={true} defaultValue={f.default} validate={validateField(f)} />;
|
return <PasswordFieldWide defaultVisible name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} defaultValue={f.default} validate={validateField(f)} />;
|
||||||
}
|
}
|
||||||
return <PasswordFieldWide name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} defaultValue={f.default} validate={validateField(f)} />;
|
return <PasswordFieldWide name={`irc.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} defaultValue={f.default} validate={validateField(f)} />;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +241,21 @@ const SettingFields = (ind: IndexerDefinition, indexer: string) => {
|
||||||
);
|
);
|
||||||
case "secret":
|
case "secret":
|
||||||
return (
|
return (
|
||||||
<PasswordFieldWide name={`settings.${f.name}`} label={f.label} required={f.required} key={idx} help={f.help} validate={validateField(f)} tooltip={<div><p>This field does not take a full URL. Only use alphanumeric strings like <code>uqcdi67cibkx3an8cmdm</code>.</p><br /><a href='https://autobrr.com/faqs#common-action-rejections' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/faqs#common-action-rejections</a></div>} />
|
<PasswordFieldWide
|
||||||
|
name={`settings.${f.name}`}
|
||||||
|
label={f.label}
|
||||||
|
required={f.required}
|
||||||
|
key={idx}
|
||||||
|
help={f.help}
|
||||||
|
validate={validateField(f)}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field does not take a full URL. Only use alphanumeric strings like <code>uqcdi67cibkx3an8cmdm</code>.</p>
|
||||||
|
<br />
|
||||||
|
<DocsLink href="https://autobrr.com/faqs#common-action-rejections" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -758,7 +789,19 @@ export function IndexerUpdateForm({ isOpen, toggle, indexer }: UpdateProps) {
|
||||||
);
|
);
|
||||||
case "secret":
|
case "secret":
|
||||||
return (
|
return (
|
||||||
<PasswordFieldWide name={`settings.${f.name}`} label={f.label} key={idx} help={f.help} tooltip={<div><p>This field does not take a full URL. Only use alphanumeric strings like <code>uqcdi67cibkx3an8cmdm</code>.</p><br /><a href='https://autobrr.com/faqs#common-action-rejections' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/faqs#common-action-rejections</a></div>} />
|
<PasswordFieldWide
|
||||||
|
key={idx}
|
||||||
|
name={`settings.${f.name}`}
|
||||||
|
label={f.label}
|
||||||
|
help={f.help}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field does not take a full URL. Only use alphanumeric strings like <code>uqcdi67cibkx3an8cmdm</code>.</p>
|
||||||
|
<br />
|
||||||
|
<DocsLink href="https://autobrr.com/faqs#common-action-rejections" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import Toast from "@components/notifications/Toast";
|
||||||
import { SlideOver } from "@components/panels";
|
import { SlideOver } from "@components/panels";
|
||||||
import { componentMapType } from "./DownloadClientForms";
|
import { componentMapType } from "./DownloadClientForms";
|
||||||
import { notificationKeys } from "@screens/settings/Notifications";
|
import { notificationKeys } from "@screens/settings/Notifications";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
const Input = (props: InputProps) => {
|
const Input = (props: InputProps) => {
|
||||||
return (
|
return (
|
||||||
|
@ -68,7 +69,14 @@ function FormFieldsDiscord() {
|
||||||
<div className="px-4 space-y-1">
|
<div className="px-4 space-y-1">
|
||||||
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
|
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
Create a <a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400">webhook integration</a> in your server.
|
{"Create a "}
|
||||||
|
<ExternalLink
|
||||||
|
href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks"
|
||||||
|
className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400"
|
||||||
|
>
|
||||||
|
webhook integration
|
||||||
|
</ExternalLink>
|
||||||
|
{" in your server."}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -107,7 +115,14 @@ function FormFieldsTelegram() {
|
||||||
<div className="px-4 space-y-1">
|
<div className="px-4 space-y-1">
|
||||||
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
|
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
Read how to <a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400">create a bot</a>.
|
{"Read how to "}
|
||||||
|
<ExternalLink
|
||||||
|
href="https://core.telegram.org/bots#3-how-do-i-create-a-bot"
|
||||||
|
className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400"
|
||||||
|
>
|
||||||
|
create a bot
|
||||||
|
</ExternalLink>
|
||||||
|
{"."}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -136,7 +151,14 @@ function FormFieldsPushover() {
|
||||||
<div className="px-4 space-y-1">
|
<div className="px-4 space-y-1">
|
||||||
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
|
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
Register a new <a href="https://support.pushover.net/i175-how-do-i-get-an-api-or-application-token" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400">application</a> and add its API Token here.
|
{"Register a new "}
|
||||||
|
<ExternalLink
|
||||||
|
href="https://support.pushover.net/i175-how-do-i-get-an-api-or-application-token"
|
||||||
|
className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400"
|
||||||
|
>
|
||||||
|
application
|
||||||
|
</ExternalLink>
|
||||||
|
{" and add its API Token here."}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { createRoot } from "react-dom/client";
|
||||||
import { Buffer } from "buffer";
|
import { Buffer } from "buffer";
|
||||||
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import "react-tooltip/dist/react-tooltip.css";
|
|
||||||
|
|
||||||
import { App } from "./App";
|
import { App } from "./App";
|
||||||
import { InitializeGlobalContext } from "./utils/Context";
|
import { InitializeGlobalContext } from "./utils/Context";
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { useState } from "react";
|
||||||
import { ChevronUpIcon, ChevronDownIcon } from "@heroicons/react/24/solid";
|
import { ChevronUpIcon, ChevronDownIcon } from "@heroicons/react/24/solid";
|
||||||
|
|
||||||
import { ReleaseTable } from "./releases/ReleaseTable";
|
import { ReleaseTable } from "./releases/ReleaseTable";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
const Code = ({ children }: { children: React.ReactNode }) => (
|
const Code = ({ children }: { children: React.ReactNode }) => (
|
||||||
<code className="rounded-md inline-block mb-1 px-1 py-0.5 border bg-gray-100 border-gray-300 dark:bg-gray-800 dark:border-gray-700">
|
<code className="rounded-md inline-block mb-1 px-1 py-0.5 border bg-gray-100 border-gray-300 dark:bg-gray-800 dark:border-gray-700">
|
||||||
|
@ -45,7 +46,7 @@ export const Releases = () => {
|
||||||
<div className="flex justify-between items-center text-base font-medium pl-2 py-1 border-b border-gray-300 bg-gray-100 dark:border-gray-700 dark:bg-gray-800 rounded-t-md">
|
<div className="flex justify-between items-center text-base font-medium pl-2 py-1 border-b border-gray-300 bg-gray-100 dark:border-gray-700 dark:bg-gray-800 rounded-t-md">
|
||||||
Search tips
|
Search tips
|
||||||
</div>
|
</div>
|
||||||
<div className={"rounded-t-md py-1 px-2 rounded-b-md bg-white dark:bg-gray-900"}>
|
<div className="rounded-t-md py-1 px-2 rounded-b-md bg-white dark:bg-gray-900">
|
||||||
You can use <b>2</b> special <span className="underline decoration-2 underline-offset-2 decoration-amber-500">wildcard characters</span> for the purpose of pattern matching.
|
You can use <b>2</b> special <span className="underline decoration-2 underline-offset-2 decoration-amber-500">wildcard characters</span> for the purpose of pattern matching.
|
||||||
<br />
|
<br />
|
||||||
- Percent (<Code>%</Code>) - for matching any <i>sequence</i> of characters (equivalent to <Code>*</Code> in Regex)
|
- Percent (<Code>%</Code>) - for matching any <i>sequence</i> of characters (equivalent to <Code>*</Code> in Regex)
|
||||||
|
@ -75,14 +76,14 @@ export const Releases = () => {
|
||||||
|
|
||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
||||||
As always, please refer to our <a
|
{"As always, please refer to our "}
|
||||||
rel="noopener noreferrer"
|
<ExternalLink
|
||||||
target="_blank"
|
|
||||||
href="https://autobrr.com/usage/search/"
|
href="https://autobrr.com/usage/search/"
|
||||||
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-purple-500 decoration-2 hover:text-black hover:dark:text-gray-100"
|
className="text-gray-700 dark:text-gray-200 underline font-semibold underline-offset-2 decoration-purple-500 decoration-2 hover:text-black hover:dark:text-gray-100"
|
||||||
>
|
>
|
||||||
Search function usage
|
Search function usage
|
||||||
</a> documentation page to keep up with the latest examples and information.
|
</ExternalLink>
|
||||||
|
{" documentation page to keep up with the latest examples and information."}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -8,13 +8,13 @@ import { useForm } from "react-hook-form";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { Tooltip } from "react-tooltip";
|
|
||||||
|
|
||||||
import { ReactComponent as Logo } from "@app/logo.svg";
|
import { ReactComponent as Logo } from "@app/logo.svg";
|
||||||
import { APIClient } from "@api/APIClient";
|
import { APIClient } from "@api/APIClient";
|
||||||
import { AuthContext } from "@utils/Context";
|
import { AuthContext } from "@utils/Context";
|
||||||
import { PasswordInput, TextInput } from "@components/inputs/text";
|
|
||||||
import Toast from "@components/notifications/Toast";
|
import Toast from "@components/notifications/Toast";
|
||||||
|
import { Tooltip } from "@components/tooltips/Tooltip";
|
||||||
|
import { PasswordInput, TextInput } from "@components/inputs/text";
|
||||||
|
|
||||||
type LoginFormFields = {
|
type LoginFormFields = {
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -103,8 +103,15 @@ export const Login = () => {
|
||||||
</button>
|
</button>
|
||||||
<div>
|
<div>
|
||||||
<span className="flex float-right items-center mt-3 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide cursor-pointer" id="forgot">
|
<span className="flex float-right items-center mt-3 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide cursor-pointer" id="forgot">
|
||||||
|
<Tooltip
|
||||||
|
label={
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
Forgot? <svg className="ml-1 w-3 h-3 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
|
Forgot? <svg className="ml-1 w-3 h-3 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
|
||||||
<Tooltip style={{ maxWidth: "350px", fontSize: "12px", textTransform: "none", fontWeight: "normal", borderRadius: "0.375rem", backgroundColor: "#34343A", color: "#fff", opacity: "1" }} place="bottom" delayShow={100} delayHide={150} anchorId="forgot" html="<p style='padding-top: 2px'>If you forget your password you can reset it via the terminal: <code>autobrrctl --config /home/username/.config/autobrr change-password <USERNAME></code></p>" clickable={true}/>
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<p className="py-1">If you forget your password you can reset it via the terminal: <code>autobrrctl --config /home/username/.config/autobrr change-password $USERNAME</code></p>
|
||||||
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { DeleteModal } from "@components/modals";
|
||||||
import { CollapsableSection } from "./Details";
|
import { CollapsableSection } from "./Details";
|
||||||
import { TextArea } from "@components/inputs/input";
|
import { TextArea } from "@components/inputs/input";
|
||||||
import Toast from "@components/notifications/Toast";
|
import Toast from "@components/notifications/Toast";
|
||||||
|
import { DocsLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
interface FilterActionsProps {
|
interface FilterActionsProps {
|
||||||
filter: Filter;
|
filter: Filter;
|
||||||
|
@ -224,7 +225,15 @@ const TypeForm = ({ action, idx, clients }: TypeFormProps) => {
|
||||||
label="Save path"
|
label="Save path"
|
||||||
columns={6}
|
columns={6}
|
||||||
placeholder="eg. /full/path/to/download_folder"
|
placeholder="eg. /full/path/to/download_folder"
|
||||||
tooltip={<div><p>Set a custom save path for this action. Automatic Torrent Management will take care of this if using qBittorrent with categories.</p><br /><p>The field can use macros to transform/add values from metadata:</p><a href='https://autobrr.com/filters/actions#macros' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/actions#macros</a></div>} />
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Set a custom save path for this action. Automatic Torrent Management will take care of this if using qBittorrent with categories.</p>
|
||||||
|
<br />
|
||||||
|
<p>The field can use macros to transform/add values from metadata:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/actions#macros" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -234,13 +243,25 @@ const TypeForm = ({ action, idx, clients }: TypeFormProps) => {
|
||||||
label="Category"
|
label="Category"
|
||||||
columns={6}
|
columns={6}
|
||||||
placeholder="eg. category"
|
placeholder="eg. category"
|
||||||
tooltip={<div><p>The field can use macros to transform/add values from metadata:</p><a href='https://autobrr.com/filters/actions#macros' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/actions#macros</a></div>} />
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>The field can use macros to transform/add values from metadata:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/actions#macros" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
name={`actions.${idx}.tags`}
|
name={`actions.${idx}.tags`}
|
||||||
label="Tags"
|
label="Tags"
|
||||||
columns={6}
|
columns={6}
|
||||||
placeholder="eg. tag1,tag2"
|
placeholder="eg. tag1,tag2"
|
||||||
tooltip={<div><p>The field can use macros to transform/add values from metadata:</p><a href='https://autobrr.com/filters/actions#macros' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/actions#macros</a></div>} />
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>The field can use macros to transform/add values from metadata:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/actions#macros" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CollapsableSection title="Rules" subtitle="client options">
|
<CollapsableSection title="Rules" subtitle="client options">
|
||||||
|
@ -282,7 +303,14 @@ const TypeForm = ({ action, idx, clients }: TypeFormProps) => {
|
||||||
<SwitchGroup
|
<SwitchGroup
|
||||||
name={`actions.${idx}.ignore_rules`}
|
name={`actions.${idx}.ignore_rules`}
|
||||||
label="Ignore client rules"
|
label="Ignore client rules"
|
||||||
tooltip={<div><p>Choose to ignore rules set in <Link className='text-blue-400 visited:text-blue-400' to="/settings/clients">Client Settings</Link>.</p></div>} />
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Choose to ignore rules set in <Link className="text-blue-400 visited:text-blue-400" to="/settings/clients">Client Settings</Link>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-6">
|
<div className="col-span-6">
|
||||||
<Select
|
<Select
|
||||||
|
|
|
@ -51,6 +51,7 @@ import { FilterActions } from "./Action";
|
||||||
import { filterKeys } from "./List";
|
import { filterKeys } from "./List";
|
||||||
import { External } from "@screens/filters/External";
|
import { External } from "@screens/filters/External";
|
||||||
import { SectionLoader } from "@components/SectionLoader";
|
import { SectionLoader } from "@components/SectionLoader";
|
||||||
|
import { DocsLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
interface tabType {
|
interface tabType {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -458,12 +459,75 @@ export function General() {
|
||||||
<TitleSubtitle title="Rules" subtitle="Specify rules on how torrents should be handled/selected." />
|
<TitleSubtitle title="Rules" subtitle="Specify rules on how torrents should be handled/selected." />
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<TextField name="min_size" label="Min size" columns={6} placeholder="eg. 100MiB, 80GB" tooltip={<div><p>Supports units such as MB, MiB, GB, etc.</p><a href='https://autobrr.com/filters#rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#rules</a></div>} />
|
<TextField
|
||||||
<TextField name="max_size" label="Max size" columns={6} placeholder="eg. 100MiB, 80GB" tooltip={<div><p>Supports units such as MB, MiB, GB, etc.</p><a href='https://autobrr.com/filters#rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#rules</a></div>} />
|
name="min_size"
|
||||||
<NumberField name="delay" label="Delay" placeholder="Number of seconds to delay actions" tooltip={<div><p>Number of seconds to wait before running actions.</p><a href='https://autobrr.com/filters#rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#rules</a></div>} />
|
label="Min size"
|
||||||
<NumberField name="priority" label="Priority" placeholder="Higher number = higher prio" tooltip={<div><p>Filters are checked in order of priority. Higher number = higher priority.</p><a href='https://autobrr.com/filters#rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#rules</a></div>} />
|
columns={6}
|
||||||
<NumberField name="max_downloads" label="Max downloads" placeholder="Takes any number (0 is infinite)" tooltip={<div><p>Number of max downloads as specified by the respective unit.</p><a href='https://autobrr.com/filters#rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#rules</a></div>} />
|
placeholder="eg. 100MiB, 80GB"
|
||||||
<Select name="max_downloads_unit" label="Max downloads per" options={downloadsPerUnitOptions} optionDefaultText="Select unit" tooltip={<div><p>The unit of time for counting the maximum downloads per filter.</p><a href='https://autobrr.com/filters#rules' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#rules</a></div>} />
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Supports units such as MB, MiB, GB, etc.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#rules" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
name="max_size"
|
||||||
|
label="Max size"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. 100MiB, 80GB"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Supports units such as MB, MiB, GB, etc.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#rules" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<NumberField
|
||||||
|
name="delay"
|
||||||
|
label="Delay"
|
||||||
|
placeholder="Number of seconds to delay actions"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Number of seconds to wait before running actions.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#rules" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<NumberField
|
||||||
|
name="priority"
|
||||||
|
label="Priority"
|
||||||
|
placeholder="Higher number = higher priority"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Filters are checked in order of priority. Higher number = higher priority.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#rules" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<NumberField
|
||||||
|
name="max_downloads"
|
||||||
|
label="Max downloads"
|
||||||
|
placeholder="Takes any number (0 is infinite)"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Number of max downloads as specified by the respective unit.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#rules" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
name="max_downloads_unit"
|
||||||
|
label="Max downloads per"
|
||||||
|
options={downloadsPerUnitOptions}
|
||||||
|
optionDefaultText="Select unit"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>The unit of time for counting the maximum downloads per filter.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#rules" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -478,43 +542,194 @@ export function MoviesTv() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<TextAreaAutoResize name="shows" label="Movies / Shows" columns={8} placeholder="eg. Movie,Show 1,Show?2" tooltip={<div><p>You can use basic filtering like wildcards <code>*</code> or replace single characters with <code>?</code></p><a href='https://autobrr.com/filters#tvmovies' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#tvmovies</a></div>} />
|
<TextAreaAutoResize
|
||||||
<TextField name="years" label="Years" columns={4} placeholder="eg. 2018,2019-2021" tooltip={<div><p>This field takes a range of years and/or comma separated single years.</p><a href='https://autobrr.com/filters#tvmovies' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#tvmovies</a></div>} />
|
name="shows"
|
||||||
|
label="Movies / Shows"
|
||||||
|
columns={8}
|
||||||
|
placeholder="eg. Movie,Show 1,Show?2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>You can use basic filtering like wildcards <code>*</code> or replace single characters with <code>?</code></p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#tvmovies" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
name="years"
|
||||||
|
label="Years"
|
||||||
|
columns={4}
|
||||||
|
placeholder="eg. 2018,2019-2021"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field takes a range of years and/or comma separated single years.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#tvmovies" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-6 lg:pb-8">
|
<div className="mt-6 lg:pb-8">
|
||||||
<TitleSubtitle title="Seasons and Episodes" subtitle="Set season and episode match constraints." />
|
<TitleSubtitle
|
||||||
|
title="Seasons and Episodes"
|
||||||
|
subtitle="Set season and episode match constraints."
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<TextField name="seasons" label="Seasons" columns={8} placeholder="eg. 1,3,2-6" tooltip={<div><p>See docs for information about how to <b>only</b> grab season packs:</p><a href='https://autobrr.com/filters/examples#only-season-packs' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/examples#only-season-packs</a></div>} />
|
<TextField
|
||||||
<TextField name="episodes" label="Episodes" columns={4} placeholder="eg. 2,4,10-20" tooltip={<div><p>See docs for information about how to <b>only</b> grab episodes:</p><a href='https://autobrr.com/filters/examples/#skip-season-packs' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/examples/#skip-season-packs</a></div>} />
|
name="seasons"
|
||||||
|
label="Seasons"
|
||||||
|
columns={8}
|
||||||
|
placeholder="eg. 1,3,2-6"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>See docs for information about how to <b>only</b> grab season packs:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/examples#only-season-packs" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
name="episodes"
|
||||||
|
label="Episodes"
|
||||||
|
columns={4}
|
||||||
|
placeholder="eg. 2,4,10-20"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>See docs for information about how to <b>only</b> grab episodes:</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/examples/#skip-season-packs" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<CheckboxField name="smart_episode" label="Smart Episode" sublabel="Do not match episodes older than the last one matched." /> {/*Do not match older or already existing episodes.*/}
|
<CheckboxField
|
||||||
|
name="smart_episode"
|
||||||
|
label="Smart Episode"
|
||||||
|
sublabel="Do not match episodes older than the last one matched."
|
||||||
|
/>{" "}
|
||||||
|
{/*Do not match older or already existing episodes.*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 lg:pb-8">
|
<div className="mt-6 lg:pb-8">
|
||||||
<TitleSubtitle title="Quality" subtitle="Set resolution, source, codec and related match constraints." />
|
<TitleSubtitle
|
||||||
|
title="Quality"
|
||||||
|
subtitle="Set resolution, source, codec and related match constraints."
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<MultiSelect name="resolutions" options={RESOLUTION_OPTIONS} label="resolutions" columns={6} creatable={true} tooltip={<div><p>Will match releases which contain any of the selected resolutions.</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
<MultiSelect
|
||||||
<MultiSelect name="sources" options={SOURCES_OPTIONS} label="sources" columns={6} creatable={true} tooltip={<div><p>Will match releases which contain any of the selected sources.</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
name="resolutions"
|
||||||
|
options={RESOLUTION_OPTIONS}
|
||||||
|
label="resolutions"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will match releases which contain any of the selected resolutions.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="sources"
|
||||||
|
options={SOURCES_OPTIONS}
|
||||||
|
label="sources"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will match releases which contain any of the selected sources.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<MultiSelect name="codecs" options={CODECS_OPTIONS} label="codecs" columns={6} creatable={true} tooltip={<div><p>Will match releases which contain any of the selected codecs.</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
<MultiSelect
|
||||||
<MultiSelect name="containers" options={CONTAINER_OPTIONS} label="containers" columns={6} creatable={true} tooltip={<div><p>Will match releases which contain any of the selected containers.</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
name="codecs"
|
||||||
|
options={CODECS_OPTIONS}
|
||||||
|
label="codecs"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will match releases which contain any of the selected codecs.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="containers"
|
||||||
|
options={CONTAINER_OPTIONS}
|
||||||
|
label="containers"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will match releases which contain any of the selected containers.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<MultiSelect name="match_hdr" options={HDR_OPTIONS} label="Match HDR" columns={6} creatable={true} tooltip={<div><p>Will match releases which contain any of the selected HDR designations.</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
<MultiSelect
|
||||||
<MultiSelect name="except_hdr" options={HDR_OPTIONS} label="Except HDR" columns={6} creatable={true} tooltip={<div><p>Won't match releases which contain any of the selected HDR designations (takes priority over Match HDR).</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
name="match_hdr"
|
||||||
|
options={HDR_OPTIONS}
|
||||||
|
label="Match HDR"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will match releases which contain any of the selected HDR designations.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="except_hdr"
|
||||||
|
options={HDR_OPTIONS}
|
||||||
|
label="Except HDR"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Won't match releases which contain any of the selected HDR designations (takes priority over Match HDR).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<MultiSelect name="match_other" options={OTHER_OPTIONS} label="Match Other" columns={6} creatable={true} tooltip={<div><p>Will match releases which contain any of the selected designations.</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
<MultiSelect
|
||||||
<MultiSelect name="except_other" options={OTHER_OPTIONS} label="Except Other" columns={6} creatable={true} tooltip={<div><p>Won't match releases which contain any of the selected Other designations (takes priority over Match Other).</p><a href='https://autobrr.com/filters#quality' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality</a></div>} />
|
name="match_other"
|
||||||
|
options={OTHER_OPTIONS}
|
||||||
|
label="Match Other"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will match releases which contain any of the selected designations.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="except_other"
|
||||||
|
options={OTHER_OPTIONS}
|
||||||
|
label="Except Other"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Won't match releases which contain any of the selected Other designations (takes priority over Match Other).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -525,47 +740,147 @@ export function Music({ values }: AdvancedProps) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<TextAreaAutoResize name="artists" label="Artists" columns={4} placeholder="eg. Artist One" tooltip={<div><p>You can use basic filtering like wildcards <code>*</code> or replace single characters with <code>?</code></p><a href='https://autobrr.com/filters#music' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#music</a></div>} />
|
<TextAreaAutoResize
|
||||||
<TextAreaAutoResize name="albums" label="Albums" columns={4} placeholder="eg. That Album" tooltip={<div><p>You can use basic filtering like wildcards <code>*</code> or replace single characters with <code>?</code></p><a href='https://autobrr.com/filters#music' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#music</a></div>} />
|
name="artists"
|
||||||
<TextField name="years" label="Years" columns={4} placeholder="eg. 2018,2019-2021" tooltip={<div><p>This field takes a range of years and/or comma separated single years.</p><a href='https://autobrr.com/filters#music' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#music</a></div>} />
|
label="Artists"
|
||||||
|
columns={4}
|
||||||
|
placeholder="eg. Artist One"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>You can use basic filtering like wildcards <code>*</code> or replace single characters with <code>?</code></p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#music" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="albums"
|
||||||
|
label="Albums"
|
||||||
|
columns={4}
|
||||||
|
placeholder="eg. That Album"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>You can use basic filtering like wildcards <code>*</code> or replace single characters with <code>?</code></p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#music" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
name="years"
|
||||||
|
label="Years"
|
||||||
|
columns={4}
|
||||||
|
placeholder="eg. 2018,2019-2021"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field takes a range of years and/or comma separated single years.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#music" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 lg:pb-8">
|
<div className="mt-6 lg:pb-8">
|
||||||
<TitleSubtitle title="Quality" subtitle="Format, source, log etc." />
|
<TitleSubtitle title="Quality" subtitle="Format, source, log etc." />
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<MultiSelect name="formats" options={FORMATS_OPTIONS} label="Format" columns={6} disabled={values.perfect_flac} tooltip={<div><p> Will only match releases with any of the selected formats. This is overridden by Perfect FLAC.</p><a href='https://autobrr.com/filters#quality-1' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality-1</a></div>} />
|
<MultiSelect
|
||||||
<MultiSelect name="quality" options={QUALITY_MUSIC_OPTIONS} label="Quality" columns={6} disabled={values.perfect_flac} tooltip={<div><p> Will only match releases with any of the selected qualities. This is overridden by Perfect FLAC.</p><a href='https://autobrr.com/filters#quality-1' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality-1</a></div>} />
|
name="formats"
|
||||||
|
options={FORMATS_OPTIONS}
|
||||||
|
label="Format"
|
||||||
|
columns={6}
|
||||||
|
disabled={values.perfect_flac}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will only match releases with any of the selected formats. This is overridden by Perfect FLAC.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality-1" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="quality"
|
||||||
|
options={QUALITY_MUSIC_OPTIONS}
|
||||||
|
label="Quality"
|
||||||
|
columns={6}
|
||||||
|
disabled={values.perfect_flac}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will only match releases with any of the selected qualities. This is overridden by Perfect FLAC.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality-1" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<MultiSelect name="media" options={SOURCES_MUSIC_OPTIONS} label="Media" columns={6} disabled={values.perfect_flac} tooltip={<div><p> Will only match releases with any of the selected sources. This is overridden by Perfect FLAC.</p><a href='https://autobrr.com/filters#quality-1' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality-1</a></div>} />
|
<MultiSelect
|
||||||
<MultiSelect name="match_release_types" options={RELEASE_TYPE_MUSIC_OPTIONS} label="Type" columns={6} tooltip={<div><p> Will only match releases with any of the selected types.</p><a href='https://autobrr.com/filters#quality-1' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality-1</a></div>} />
|
name="media"
|
||||||
|
options={SOURCES_MUSIC_OPTIONS}
|
||||||
|
label="Media"
|
||||||
|
columns={6}
|
||||||
|
disabled={values.perfect_flac}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will only match releases with any of the selected sources. This is overridden by Perfect FLAC.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality-1" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="match_release_types"
|
||||||
|
options={RELEASE_TYPE_MUSIC_OPTIONS}
|
||||||
|
label="Type"
|
||||||
|
columns={6}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Will only match releases with any of the selected types.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality-1" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-12 gap-6">
|
<div className="mt-6 grid grid-cols-12 gap-6">
|
||||||
<NumberField name="log_score" label="Log score" placeholder="eg. 100" min={0} max={100} disabled={values.perfect_flac} tooltip={<div><p> Log scores go from 0 to 100. This is overridden by Perfect FLAC.</p><a href='https://autobrr.com/filters#quality-1' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality-1</a></div>} />
|
<NumberField
|
||||||
|
name="log_score"
|
||||||
|
label="Log score"
|
||||||
|
placeholder="eg. 100"
|
||||||
|
min={0}
|
||||||
|
max={100}
|
||||||
|
disabled={values.perfect_flac}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Log scores go from 0 to 100. This is overridden by Perfect FLAC.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality-1" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-6 sm:space-y-5 divide-y divide-gray-200">
|
|
||||||
<div className="pt-6 sm:pt-5">
|
|
||||||
<div role="group" aria-labelledby="label-email">
|
|
||||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||||
{/* <div>
|
|
||||||
<div className="text-base font-medium text-gray-900 sm:text-sm sm:text-gray-700" >
|
|
||||||
Extra
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||||
<div className="max-w-lg space-y-4">
|
<div className="max-w-lg space-y-4">
|
||||||
<CheckboxField name="log" label="Log" sublabel="Must include Log." disabled={values.perfect_flac} />
|
<CheckboxField
|
||||||
<CheckboxField name="cue" label="Cue" sublabel="Must include Cue." disabled={values.perfect_flac} />
|
name="log"
|
||||||
<CheckboxField name="perfect_flac" label="Perfect FLAC" sublabel="Override all options about quality, source, format, and cue/log/log score." tooltip={<div><p>Override all options about quality, source, format, and cue/log/log score.</p><a href='https://autobrr.com/filters#quality-1' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#quality-1</a></div>} />
|
label="Log"
|
||||||
</div>
|
sublabel="Must include Log."
|
||||||
</div>
|
disabled={values.perfect_flac}
|
||||||
|
/>
|
||||||
|
<CheckboxField
|
||||||
|
name="cue"
|
||||||
|
label="Cue"
|
||||||
|
sublabel="Must include Cue."
|
||||||
|
disabled={values.perfect_flac}
|
||||||
|
/>
|
||||||
|
<CheckboxField
|
||||||
|
name="perfect_flac"
|
||||||
|
label="Perfect FLAC"
|
||||||
|
sublabel="Override all options about quality, source, format, and cue/log/log score."
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Override all options about quality, source, format, and cue/log/log score.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#quality-1" />
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -580,18 +895,54 @@ interface AdvancedProps {
|
||||||
export function Advanced({ values }: AdvancedProps) {
|
export function Advanced({ values }: AdvancedProps) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CollapsableSection defaultOpen={true} title="Releases" subtitle="Match only certain release names and/or ignore other release names.">
|
<CollapsableSection
|
||||||
|
defaultOpen
|
||||||
|
title="Releases"
|
||||||
|
subtitle="Match only certain release names and/or ignore other release names."
|
||||||
|
>
|
||||||
<div className="grid col-span-12 gap-6">
|
<div className="grid col-span-12 gap-6">
|
||||||
<WarningAlert text="autobrr has extensive filtering built-in - only use this if nothing else works. If you need help, please ask." />
|
<WarningAlert text="autobrr has extensive filtering built-in - only use this if nothing else works. If you need help, please ask." />
|
||||||
|
|
||||||
<RegexTextAreaField name="match_releases" label="Match releases" useRegex={values.use_regex} columns={6} placeholder="eg. *some?movie*,*some?show*s01*" tooltip={<div><p>This field has full regex support (Golang flavour).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a><br /><br /><p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p></div>} />
|
<RegexTextAreaField
|
||||||
<RegexTextAreaField name="except_releases" label="Except releases" useRegex={values.use_regex} columns={6} placeholder="eg. *bad?movie*,*bad?show*s03*" tooltip={<div><p>This field has full regex support (Golang flavour).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a><br /><br /><p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p></div>} />
|
name="match_releases"
|
||||||
|
label="Match releases"
|
||||||
|
useRegex={values.use_regex}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *some?movie*,*some?show*s01*"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field has full regex support (Golang flavour).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<RegexTextAreaField
|
||||||
|
name="except_releases"
|
||||||
|
label="Except releases"
|
||||||
|
useRegex={values.use_regex}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *bad?movie*,*bad?show*s03*"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field has full regex support (Golang flavour).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
{values.match_releases ? (
|
{values.match_releases ? (
|
||||||
<WarningAlert
|
<WarningAlert
|
||||||
alert="Ask yourself:"
|
alert="Ask yourself:"
|
||||||
text={
|
text={
|
||||||
<>Do you have a good reason to use <strong>Match releases</strong> instead of one of the other tabs?</>
|
<>
|
||||||
|
Do you have a good reason to use <strong>Match releases</strong> instead of one of the other tabs?
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
colors="text-cyan-700 bg-cyan-100 dark:bg-cyan-200 dark:text-cyan-800"
|
colors="text-cyan-700 bg-cyan-100 dark:bg-cyan-200 dark:text-cyan-800"
|
||||||
/>
|
/>
|
||||||
|
@ -600,7 +951,9 @@ export function Advanced({ values }: AdvancedProps) {
|
||||||
<WarningAlert
|
<WarningAlert
|
||||||
alert="Ask yourself:"
|
alert="Ask yourself:"
|
||||||
text={
|
text={
|
||||||
<>Do you have a good reason to use <strong>Except releases</strong> instead of one of the other tabs?</>
|
<>
|
||||||
|
Do you have a good reason to use <strong>Except releases</strong> instead of one of the other tabs?
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
colors="text-fuchsia-700 bg-fuchsia-100 dark:bg-fuchsia-200 dark:text-fuchsia-800"
|
colors="text-fuchsia-700 bg-fuchsia-100 dark:bg-fuchsia-200 dark:text-fuchsia-800"
|
||||||
/>
|
/>
|
||||||
|
@ -611,42 +964,215 @@ export function Advanced({ values }: AdvancedProps) {
|
||||||
</div>
|
</div>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Groups" subtitle="Match only certain groups and/or ignore other groups.">
|
<CollapsableSection
|
||||||
<TextAreaAutoResize name="match_release_groups" label="Match release groups" columns={6} placeholder="eg. group1,group2" tooltip={<div><p>Comma separated list of release groups to match.</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
defaultOpen={true}
|
||||||
<TextAreaAutoResize name="except_release_groups" label="Except release groups" columns={6} placeholder="eg. badgroup1,badgroup2" tooltip={<div><p>Comma separated list of release groups to ignore (takes priority over Match releases).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
title="Groups"
|
||||||
|
subtitle="Match only certain groups and/or ignore other groups."
|
||||||
|
>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="match_release_groups"
|
||||||
|
label="Match release groups"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. group1,group2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of release groups to match.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="except_release_groups"
|
||||||
|
label="Except release groups"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. badgroup1,badgroup2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of release groups to ignore (takes priority over Match releases).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Categories and tags" subtitle="Match or ignore categories or tags.">
|
<CollapsableSection
|
||||||
<TextAreaAutoResize name="match_categories" label="Match categories" columns={6} placeholder="eg. *category*,category1" tooltip={<div><p>Comma separated list of categories to match.</p><a href='https://autobrr.com/filters/categories' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/categories</a></div>} />
|
defaultOpen={true}
|
||||||
<TextAreaAutoResize name="except_categories" label="Except categories" columns={6} placeholder="eg. *category*" tooltip={<div><p>Comma separated list of categories to ignore (takes priority over Match releases).</p><a href='https://autobrr.com/filters/categories' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/categories</a></div>} />
|
title="Categories and tags"
|
||||||
|
subtitle="Match or ignore categories or tags."
|
||||||
|
>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="match_categories"
|
||||||
|
label="Match categories"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *category*,category1"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of categories to match.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/categories" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="except_categories"
|
||||||
|
label="Except categories"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *category*"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of categories to ignore (takes priority over Match releases).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters/categories" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<TextAreaAutoResize name="tags" label="Match tags" columns={4} placeholder="eg. tag1,tag2" tooltip={<div><p>Comma separated list of tags to match.</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
<TextAreaAutoResize
|
||||||
<Select name="tags_match_logic" label="Tags logic" columns={2} options={tagsMatchLogicOptions} optionDefaultText="any" tooltip={<div><p>Logic used to match filter tags.</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
name="tags"
|
||||||
<TextAreaAutoResize name="except_tags" label="Except tags" columns={4} placeholder="eg. tag1,tag2" tooltip={<div><p>Comma separated list of tags to ignore (takes priority over Match releases).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>hhttps://autobrr.com/filters#advanced</a></div>} />
|
label="Match tags"
|
||||||
<Select name="except_tags_match_logic" label="Except tags logic" columns={2} options={tagsMatchLogicOptions} optionDefaultText="any" tooltip={<div><p>Logic used to match except tags.</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
columns={4}
|
||||||
|
placeholder="eg. tag1,tag2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of tags to match.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
name="tags_match_logic"
|
||||||
|
label="Tags logic"
|
||||||
|
columns={2}
|
||||||
|
options={tagsMatchLogicOptions}
|
||||||
|
optionDefaultText="any"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Logic used to match filter tags.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="except_tags"
|
||||||
|
label="Except tags"
|
||||||
|
columns={4}
|
||||||
|
placeholder="eg. tag1,tag2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of tags to ignore (takes priority over Match releases).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
name="except_tags_match_logic"
|
||||||
|
label="Except tags logic"
|
||||||
|
columns={2}
|
||||||
|
options={tagsMatchLogicOptions}
|
||||||
|
optionDefaultText="any"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Logic used to match except tags.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Uploaders" subtitle="Match or ignore uploaders.">
|
<CollapsableSection
|
||||||
<TextAreaAutoResize name="match_uploaders" label="Match uploaders" columns={6} placeholder="eg. uploader1,uploader2" tooltip={<div><p>Comma separated list of uploaders to match.</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
defaultOpen={true}
|
||||||
<TextAreaAutoResize name="except_uploaders" label="Except uploaders" columns={6} placeholder="eg. anonymous1,anonymous2" tooltip={<div><p>Comma separated list of uploaders to ignore (takes priority over Match releases).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a></div>} />
|
title="Uploaders"
|
||||||
|
subtitle="Match or ignore uploaders."
|
||||||
|
>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="match_uploaders"
|
||||||
|
label="Match uploaders"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. uploader1,uploader2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of uploaders to match.</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextAreaAutoResize
|
||||||
|
name="except_uploaders"
|
||||||
|
label="Except uploaders"
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. anonymous1,anonymous2"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>Comma separated list of uploaders to ignore (takes priority over Match releases).
|
||||||
|
</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Language" subtitle="Match or ignore languages.">
|
<CollapsableSection
|
||||||
<MultiSelect name="match_language" options={LANGUAGE_OPTIONS} label="Match Language" columns={6} creatable={true} />
|
defaultOpen={true}
|
||||||
<MultiSelect name="except_language" options={LANGUAGE_OPTIONS} label="Except Language" columns={6} creatable={true} />
|
title="Language"
|
||||||
|
subtitle="Match or ignore languages."
|
||||||
|
>
|
||||||
|
<MultiSelect
|
||||||
|
name="match_language"
|
||||||
|
options={LANGUAGE_OPTIONS}
|
||||||
|
label="Match Language"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="except_language"
|
||||||
|
options={LANGUAGE_OPTIONS}
|
||||||
|
label="Except Language"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
/>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Origins" subtitle="Match Internals, scene, p2p etc. if announced.">
|
<CollapsableSection
|
||||||
<MultiSelect name="origins" options={ORIGIN_OPTIONS} label="Match Origins" columns={6} creatable={true} />
|
defaultOpen={true}
|
||||||
<MultiSelect name="except_origins" options={ORIGIN_OPTIONS} label="Except Origins" columns={6} creatable={true} />
|
title="Origins"
|
||||||
|
subtitle="Match Internals, scene, p2p etc. if announced."
|
||||||
|
>
|
||||||
|
<MultiSelect
|
||||||
|
name="origins"
|
||||||
|
options={ORIGIN_OPTIONS}
|
||||||
|
label="Match Origins"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
name="except_origins"
|
||||||
|
options={ORIGIN_OPTIONS}
|
||||||
|
label="Except Origins"
|
||||||
|
columns={6}
|
||||||
|
creatable={true}
|
||||||
|
/>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Release Tags" subtitle="This is the non-parsed releaseTags string from the announce.">
|
<CollapsableSection
|
||||||
|
defaultOpen={true}
|
||||||
|
title="Release Tags"
|
||||||
|
subtitle="This is the non-parsed releaseTags string from the announce."
|
||||||
|
>
|
||||||
<div className="grid col-span-12 gap-6">
|
<div className="grid col-span-12 gap-6">
|
||||||
<WarningAlert text="These might not be what you think they are. For advanced users who know how things are parsed." />
|
<WarningAlert text="These might not be what you think they are. For advanced users who know how things are parsed." />
|
||||||
|
|
||||||
<RegexField name="match_release_tags" label="Match release tags" useRegex={values.use_regex_release_tags} columns={6} placeholder="eg. *mkv*,*foreign*" />
|
<RegexField
|
||||||
<RegexField name="except_release_tags" label="Except release tags" useRegex={values.use_regex_release_tags} columns={6} placeholder="eg. *mkv*,*foreign*" />
|
name="match_release_tags"
|
||||||
|
label="Match release tags"
|
||||||
|
useRegex={values.use_regex_release_tags}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *mkv*,*foreign*"
|
||||||
|
/>
|
||||||
|
<RegexField
|
||||||
|
name="except_release_tags"
|
||||||
|
label="Except release tags"
|
||||||
|
useRegex={values.use_regex_release_tags}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *mkv*,*foreign*"
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="col-span-6">
|
<div className="col-span-6">
|
||||||
<SwitchGroup name="use_regex_release_tags" label="Use Regex" />
|
<SwitchGroup name="use_regex_release_tags" label="Use Regex" />
|
||||||
|
@ -654,10 +1180,44 @@ export function Advanced({ values }: AdvancedProps) {
|
||||||
</div>
|
</div>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Feeds" subtitle="These options are only for Feeds such as RSS, Torznab and Newznab">
|
<CollapsableSection
|
||||||
|
defaultOpen={true}
|
||||||
|
title="Feeds"
|
||||||
|
subtitle="These options are only for Feeds such as RSS, Torznab and Newznab"
|
||||||
|
>
|
||||||
{/*<div className="grid col-span-12 gap-6">*/}
|
{/*<div className="grid col-span-12 gap-6">*/}
|
||||||
<RegexTextAreaField name="match_description" label="Match description" useRegex={values.use_regex_description} columns={6} placeholder="eg. *some?movie*,*some?show*s01*" tooltip={<div><p>This field has full regex support (Golang flavour).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a><br /><br /><p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p></div>} />
|
<RegexTextAreaField
|
||||||
<RegexTextAreaField name="except_description" label="Except description" useRegex={values.use_regex_description} columns={6} placeholder="eg. *bad?movie*,*bad?show*s03*" tooltip={<div><p>This field has full regex support (Golang flavour).</p><a href='https://autobrr.com/filters#advanced' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters#advanced</a><br /><br /><p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p></div>} />
|
name="match_description"
|
||||||
|
label="Match description"
|
||||||
|
useRegex={values.use_regex_description}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *some?movie*,*some?show*s01*"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field has full regex support (Golang flavour).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<RegexTextAreaField
|
||||||
|
name="except_description"
|
||||||
|
label="Except description"
|
||||||
|
useRegex={values.use_regex_description}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. *bad?movie*,*bad?show*s03*"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>This field has full regex support (Golang flavour).</p>
|
||||||
|
<DocsLink href="https://autobrr.com/filters#advanced" />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<p>Remember to tick <b>Use Regex</b> below if using more than <code>*</code> and <code>?</code>.</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
{/*</div>*/}
|
{/*</div>*/}
|
||||||
|
|
||||||
<div className="col-span-6">
|
<div className="col-span-6">
|
||||||
|
@ -665,12 +1225,53 @@ export function Advanced({ values }: AdvancedProps) {
|
||||||
</div>
|
</div>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
|
|
||||||
<CollapsableSection defaultOpen={true} title="Freeleech" subtitle="Match only freeleech and freeleech percent.">
|
<CollapsableSection
|
||||||
|
defaultOpen={true}
|
||||||
|
title="Freeleech"
|
||||||
|
subtitle="Match only freeleech and freeleech percent."
|
||||||
|
>
|
||||||
<div className="col-span-6">
|
<div className="col-span-6">
|
||||||
<SwitchGroup name="freeleech" label="Freeleech" tooltip={<div><p>Freeleech may be announced as a binary true/false value or as a percentage, depending on the indexer. Use either or both, depending on the indexers you use.</p><br /><p>See who uses what in the documentation: <a href='https://autobrr.com/filters/freeleech' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/freeleech</a></p></div>} />
|
<SwitchGroup
|
||||||
|
name="freeleech"
|
||||||
|
label="Freeleech"
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Freeleech may be announced as a binary true/false value or as
|
||||||
|
a percentage, depending on the indexer. Use either or both,
|
||||||
|
depending on the indexers you use.
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
See who uses what in the documentation:{" "}
|
||||||
|
<DocsLink href="https://autobrr.com/filters/freeleech" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextField name="freeleech_percent" label="Freeleech percent" disabled={values.freeleech} tooltip={<div><p>Freeleech may be announced as a binary true/false value or as a percentage, depending on the indexer. Use either or both, depending on the indexers you use.</p><br /><p>See who uses what in the documentation: <a href='https://autobrr.com/filters/freeleech' className='text-blue-400 visited:text-blue-400' target='_blank'>https://autobrr.com/filters/freeleech</a></p></div>} columns={6} placeholder="eg. 50,75-100" />
|
<TextField
|
||||||
|
name="freeleech_percent"
|
||||||
|
label="Freeleech percent"
|
||||||
|
disabled={values.freeleech}
|
||||||
|
tooltip={
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Freeleech may be announced as a binary true/false value or as a
|
||||||
|
percentage, depending on the indexer. Use either or both,
|
||||||
|
depending on the indexers you use.
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
See who uses what in the documentation:{" "}
|
||||||
|
<DocsLink href="https://autobrr.com/filters/freeleech" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
columns={6}
|
||||||
|
placeholder="eg. 50,75-100"
|
||||||
|
/>
|
||||||
</CollapsableSection>
|
</CollapsableSection>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import { ChevronRightIcon } from "@heroicons/react/24/solid";
|
import { ChevronRightIcon } from "@heroicons/react/24/solid";
|
||||||
import { DeleteModal } from "@components/modals";
|
import { DeleteModal } from "@components/modals";
|
||||||
import { ArrowDownIcon, ArrowUpIcon } from "@heroicons/react/24/outline";
|
import { ArrowDownIcon, ArrowUpIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { DocsLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export function External() {
|
export function External() {
|
||||||
const { values } = useFormikContext<Filter>();
|
const { values } = useFormikContext<Filter>();
|
||||||
|
@ -261,11 +262,7 @@ const TypeForm = ({ external, idx }: TypeFormProps) => {
|
||||||
For custom commands you should specify the full path to the binary/program
|
For custom commands you should specify the full path to the binary/program
|
||||||
you want to run. And you can include your own static variables:
|
you want to run. And you can include your own static variables:
|
||||||
</p>
|
</p>
|
||||||
<a
|
<DocsLink href="https://autobrr.com/filters/actions#custom-commands--exec" />
|
||||||
href="https://autobrr.com/filters/actions#custom-commands--exec"
|
|
||||||
className="text-blue-400 visited:text-blue-400"
|
|
||||||
target="_blank">https://autobrr.com/filters/actions#custom-commands--exec
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,7 +10,6 @@ import { Listbox, Menu, Switch, Transition } from "@headlessui/react";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import { FormikValues } from "formik";
|
import { FormikValues } from "formik";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { Tooltip } from "react-tooltip";
|
|
||||||
import {
|
import {
|
||||||
ArrowsRightLeftIcon,
|
ArrowsRightLeftIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
|
@ -35,6 +34,7 @@ import { EmptyListState } from "@components/emptystates";
|
||||||
import { DeleteModal } from "@components/modals";
|
import { DeleteModal } from "@components/modals";
|
||||||
|
|
||||||
import { Importer } from "./Importer";
|
import { Importer } from "./Importer";
|
||||||
|
import { Tooltip } from "@components/tooltips/Tooltip";
|
||||||
|
|
||||||
export const filterKeys = {
|
export const filterKeys = {
|
||||||
all: ["filters"] as const,
|
all: ["filters"] as const,
|
||||||
|
@ -96,7 +96,7 @@ export function Filters() {
|
||||||
setIsOpen={setShowImportModal}
|
setIsOpen={setShowImportModal}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-between items-center flex-col sm:flex-row my-6 max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="flex justify-between items-center flex-row flex-wrap my-6 max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h1 className="text-3xl font-bold text-black dark:text-white">Filters</h1>
|
<h1 className="text-3xl font-bold text-black dark:text-white">Filters</h1>
|
||||||
<Menu as="div" className="relative">
|
<Menu as="div" className="relative">
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
|
@ -635,49 +635,30 @@ function FilterListItem({ filter, values, idx }: FilterListItemProps) {
|
||||||
Priority: {filter.priority}
|
Priority: {filter.priority}
|
||||||
</span>
|
</span>
|
||||||
<span className="whitespace-nowrap text-xs font-medium text-gray-600 dark:text-gray-400">
|
<span className="whitespace-nowrap text-xs font-medium text-gray-600 dark:text-gray-400">
|
||||||
|
<Tooltip
|
||||||
|
label={
|
||||||
<Link
|
<Link
|
||||||
to={`${filter.id.toString()}/actions`}
|
to={`${filter.id.toString()}/actions`}
|
||||||
className="hover:text-black dark:hover:text-gray-300"
|
className="flex items-center cursor-pointer hover:text-black dark:hover:text-gray-300"
|
||||||
>
|
|
||||||
<span
|
|
||||||
id={`tooltip-actions-${filter.id}`}
|
|
||||||
className="flex items-center hover:cursor-pointer"
|
|
||||||
>
|
|
||||||
<span className={classNames(filter.actions_count == 0 ? "text-red-500" : "")}>
|
|
||||||
<span
|
|
||||||
className={
|
|
||||||
classNames(
|
|
||||||
filter.actions_count == 0 ? "hover:text-red-400 dark:hover:text-red-400" : ""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
|
<span className={classNames(!filter.actions_count ? "text-red-500 hover:text-red-400 dark:hover:text-red-400" : "")}>
|
||||||
Actions: {filter.actions_count}
|
Actions: {filter.actions_count}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
{!filter.actions_count && (
|
||||||
{filter.actions_count === 0 && (
|
|
||||||
<>
|
|
||||||
<span className="mr-2 ml-2 flex h-3 w-3 relative">
|
<span className="mr-2 ml-2 flex h-3 w-3 relative">
|
||||||
<span className="animate-ping inline-flex h-full w-full rounded-full dark:bg-red-500 bg-red-400 opacity-75" />
|
<span className="animate-ping inline-flex h-full w-full rounded-full dark:bg-red-500 bg-red-400 opacity-75" />
|
||||||
<span
|
<span
|
||||||
className="inline-flex absolute rounded-full h-3 w-3 dark:bg-red-500 bg-red-400"
|
className="inline-flex absolute rounded-full h-3 w-3 dark:bg-red-500 bg-red-400"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span className="text-sm text-gray-800 dark:text-gray-500">
|
|
||||||
<Tooltip
|
|
||||||
style={{ width: "350px", fontSize: "12px", textTransform: "none", fontWeight: "normal", borderRadius: "0.375rem", backgroundColor: "#34343A", color: "#fff", whiteSpace: "pre-wrap", overflow: "hidden", textOverflow: "ellipsis" }}
|
|
||||||
delayShow={100}
|
|
||||||
delayHide={150}
|
|
||||||
data-html={true}
|
|
||||||
place="right"
|
|
||||||
data-tooltip-id={`tooltip-actions-${filter.id}`}
|
|
||||||
>
|
|
||||||
<p>You need to setup an action in the filter otherwise you will not get any snatches.</p>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{!filter.actions_count ? (
|
||||||
|
<>{"You need to setup an action in the filter otherwise you will not get any snatches."}</>
|
||||||
|
) : null}
|
||||||
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -140,7 +140,8 @@ export const PushStatusSelectColumnFilter = ({
|
||||||
))}
|
))}
|
||||||
</ListboxFilter>
|
</ListboxFilter>
|
||||||
</div>
|
</div>
|
||||||
);};
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const SearchColumnFilter = ({
|
export const SearchColumnFilter = ({
|
||||||
column: { filterValue, setFilter, id }
|
column: { filterValue, setFilter, id }
|
||||||
|
@ -161,4 +162,5 @@ export const SearchColumnFilter = ({
|
||||||
placeholder="Search releases..."
|
placeholder="Search releases..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);};
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { IndexerSelectColumnFilter, PushStatusSelectColumnFilter, SearchColumnFi
|
||||||
import { classNames } from "@utils";
|
import { classNames } from "@utils";
|
||||||
import { ArrowTopRightOnSquareIcon, ArrowDownTrayIcon } from "@heroicons/react/24/outline";
|
import { ArrowTopRightOnSquareIcon, ArrowDownTrayIcon } from "@heroicons/react/24/outline";
|
||||||
import { Tooltip } from "@components/tooltips/Tooltip";
|
import { Tooltip } from "@components/tooltips/Tooltip";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export const releaseKeys = {
|
export const releaseKeys = {
|
||||||
all: ["releases"] as const,
|
all: ["releases"] as const,
|
||||||
|
@ -103,24 +104,17 @@ export const ReleaseTable = () => {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<div className="flex mr-0">
|
<div className="flex mr-0">
|
||||||
{props.row.original.download_url && (
|
{props.row.original.download_url && (
|
||||||
<a
|
<ExternalLink
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href={props.row.original.download_url}
|
href={props.row.original.download_url}
|
||||||
className="max-w-[90vw] px-2"
|
className="px-2"
|
||||||
>
|
>
|
||||||
<ArrowDownTrayIcon className="h-5 w-5 text-blue-400 hover:text-blue-500 dark:text-blue-500 dark:hover:text-blue-600" aria-hidden="true" />
|
<ArrowDownTrayIcon className="h-5 w-5 text-blue-400 hover:text-blue-500 dark:text-blue-500 dark:hover:text-blue-600" aria-hidden="true" />
|
||||||
</a>
|
</ExternalLink>
|
||||||
)}
|
)}
|
||||||
{props.row.original.info_url && (
|
{props.row.original.info_url && (
|
||||||
<a
|
<ExternalLink href={props.row.original.info_url}>
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
href={props.row.original.info_url}
|
|
||||||
className="max-w-[90vw]"
|
|
||||||
>
|
|
||||||
<ArrowTopRightOnSquareIcon className="h-5 w-5 text-blue-400 hover:text-blue-500 dark:text-blue-500 dark:hover:text-blue-600" aria-hidden="true" />
|
<ArrowTopRightOnSquareIcon className="h-5 w-5 text-blue-400 hover:text-blue-500 dark:text-blue-500 dark:hover:text-blue-600" aria-hidden="true" />
|
||||||
</a>
|
</ExternalLink>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { Checkbox } from "@components/Checkbox";
|
||||||
import { SettingsContext } from "@utils/Context";
|
import { SettingsContext } from "@utils/Context";
|
||||||
import { GithubRelease } from "@app/types/Update";
|
import { GithubRelease } from "@app/types/Update";
|
||||||
import Toast from "@components/notifications/Toast";
|
import Toast from "@components/notifications/Toast";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
interface RowItemProps {
|
interface RowItemProps {
|
||||||
label: string;
|
label: string;
|
||||||
|
@ -63,9 +64,12 @@ const RowItemVersion = ({ label, value, title, newUpdate }: RowItemProps) => {
|
||||||
<dd className="mt-1 text-gray-900 dark:text-gray-300 text-sm sm:mt-0 sm:col-span-2 break-all truncate">
|
<dd className="mt-1 text-gray-900 dark:text-gray-300 text-sm sm:mt-0 sm:col-span-2 break-all truncate">
|
||||||
<span className="px-1.5 py-1 bg-gray-200 dark:bg-gray-700 rounded shadow">{value}</span>
|
<span className="px-1.5 py-1 bg-gray-200 dark:bg-gray-700 rounded shadow">{value}</span>
|
||||||
{newUpdate && newUpdate.html_url && (
|
{newUpdate && newUpdate.html_url && (
|
||||||
<span>
|
<ExternalLink
|
||||||
<a href={newUpdate.html_url} target="_blank" rel="noopener noreferrer"><span className="ml-2 inline-flex items-center rounded-md bg-green-100 px-2.5 py-0.5 text-sm font-medium text-green-800">{newUpdate.name} available!</span></a>
|
href={newUpdate.html_url}
|
||||||
</span>
|
className="ml-2 inline-flex items-center rounded-md bg-green-100 px-2.5 py-0.5 text-sm font-medium text-green-800"
|
||||||
|
>
|
||||||
|
{newUpdate.name} available!
|
||||||
|
</ExternalLink>
|
||||||
)}
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -184,10 +188,12 @@ function ApplicationSettings() {
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="WebUI Debug mode"
|
label="WebUI Debug mode"
|
||||||
value={settings.debug}
|
value={settings.debug}
|
||||||
setValue={(newValue: boolean) => setSettings({
|
setValue={
|
||||||
...settings,
|
(newValue: boolean) => setSettings((prevState) => ({
|
||||||
|
...prevState,
|
||||||
debug: newValue
|
debug: newValue
|
||||||
})}
|
}))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 sm:px-6 py-1">
|
<div className="px-4 sm:px-6 py-1">
|
||||||
|
@ -205,15 +211,16 @@ function ApplicationSettings() {
|
||||||
label="Dark theme"
|
label="Dark theme"
|
||||||
description="Switch between dark and light theme."
|
description="Switch between dark and light theme."
|
||||||
value={settings.darkTheme}
|
value={settings.darkTheme}
|
||||||
setValue={(newValue: boolean) => setSettings({
|
setValue={
|
||||||
...settings,
|
(newValue: boolean) => setSettings((prevState) => ({
|
||||||
|
...prevState,
|
||||||
darkTheme: newValue
|
darkTheme: newValue
|
||||||
})}
|
}))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { FeedUpdateForm } from "@forms/settings/FeedForms";
|
||||||
import { EmptySimple } from "@components/emptystates";
|
import { EmptySimple } from "@components/emptystates";
|
||||||
import { ImplementationBadges } from "./Indexer";
|
import { ImplementationBadges } from "./Indexer";
|
||||||
import { ArrowPathIcon } from "@heroicons/react/24/solid";
|
import { ArrowPathIcon } from "@heroicons/react/24/solid";
|
||||||
|
import { ExternalLink } from "@components/ExternalLink";
|
||||||
|
|
||||||
export const feedKeys = {
|
export const feedKeys = {
|
||||||
all: ["feeds"] as const,
|
all: ["feeds"] as const,
|
||||||
|
@ -354,10 +355,8 @@ const FeedItemDropdown = ({
|
||||||
<div>
|
<div>
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
{({ active }) => (
|
{({ active }) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href={`${baseUrl()}api/feeds/${feed.id}/latest`}
|
href={`${baseUrl()}api/feeds/${feed.id}/latest`}
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active ? "bg-blue-600 text-white" : "text-gray-900 dark:text-gray-300",
|
active ? "bg-blue-600 text-white" : "text-gray-900 dark:text-gray-300",
|
||||||
"font-medium group flex rounded-md items-center w-full px-2 py-2 text-sm"
|
"font-medium group flex rounded-md items-center w-full px-2 py-2 text-sm"
|
||||||
|
@ -371,7 +370,7 @@ const FeedItemDropdown = ({
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
View latest run
|
View latest run
|
||||||
</a>
|
</ExternalLink>
|
||||||
)}
|
)}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue