mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 16:59:12 +00:00
fix(web): TS typings and always active navbar link (#470)
* fix TS typings since `yarn build` was failing on my machine. * fixed the dashboard navlink (it was always active on my end)
This commit is contained in:
parent
8a782a5cab
commit
553320bf1d
5 changed files with 60 additions and 35 deletions
|
@ -4,6 +4,7 @@ import { classNames, get } from "../../utils";
|
||||||
import { useToggle } from "../../hooks/hooks";
|
import { useToggle } from "../../hooks/hooks";
|
||||||
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid";
|
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid";
|
||||||
import { ErrorMessage } from "@hookform/error-message";
|
import { ErrorMessage } from "@hookform/error-message";
|
||||||
|
import type { FieldValues } from "react-hook-form";
|
||||||
|
|
||||||
export type FormErrorMessageProps = {
|
export type FormErrorMessageProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -81,7 +82,7 @@ export const Input: FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(
|
||||||
export type FormInputProps<TFormValues> = {
|
export type FormInputProps<TFormValues> = {
|
||||||
name: Path<TFormValues>;
|
name: Path<TFormValues>;
|
||||||
rules?: RegisterOptions;
|
rules?: RegisterOptions;
|
||||||
register?: UseFormRegister<TFormValues>;
|
register?: UseFormRegister<TFormValues & FieldValues>;
|
||||||
errors?: Partial<DeepMap<TFormValues, FieldError>>;
|
errors?: Partial<DeepMap<TFormValues, FieldError>>;
|
||||||
} & Omit<InputProps, "name">;
|
} & Omit<InputProps, "name">;
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
import React, {Fragment, useRef} from "react";
|
import React, { Fragment, useRef } from "react";
|
||||||
import {XMarkIcon} from "@heroicons/react/24/solid";
|
import { XMarkIcon } from "@heroicons/react/24/solid";
|
||||||
import {Dialog, Transition} from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
import {Form, Formik} from "formik";
|
import { Form, Formik } from "formik";
|
||||||
|
import type { FormikValues } from "formik";
|
||||||
import DEBUG from "../debug";
|
import DEBUG from "../debug";
|
||||||
import {useToggle} from "../../hooks/hooks";
|
import { useToggle } from "../../hooks/hooks";
|
||||||
import {DeleteModal} from "../modals";
|
import { DeleteModal } from "../modals";
|
||||||
import {classNames} from "../../utils";
|
import { classNames } from "../../utils";
|
||||||
|
|
||||||
interface SlideOverProps<DataType> {
|
interface SlideOverProps<DataType> {
|
||||||
title: string;
|
title: string;
|
||||||
initialValues: DataType;
|
initialValues: FormikValues & DataType;
|
||||||
validate?: (values: DataType) => void;
|
validate?: (values: DataType) => void;
|
||||||
onSubmit: (values?: DataType) => void;
|
onSubmit: (values?: DataType) => void;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
toggle: () => void;
|
toggle: () => void;
|
||||||
children?: (values: DataType) => React.ReactNode;
|
children?: (values: DataType) => React.ReactNode;
|
||||||
deleteAction?: () => void;
|
deleteAction?: () => void;
|
||||||
type: "CREATE" | "UPDATE";
|
type: "CREATE" | "UPDATE";
|
||||||
testFn?: (data: unknown) => void;
|
testFn?: (data: unknown) => void;
|
||||||
isTesting?: boolean;
|
isTesting?: boolean;
|
||||||
isTestSuccessful?: boolean;
|
isTestSuccessful?: boolean;
|
||||||
isTestError?: boolean;
|
isTestError?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SlideOver<DataType>({
|
function SlideOver<DataType>({
|
||||||
|
@ -81,7 +82,7 @@ function SlideOver<DataType>({
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
validate={validate}
|
validate={validate}
|
||||||
>
|
>
|
||||||
{({ handleSubmit, values }) => (
|
{({ handleSubmit, values }) => (
|
||||||
<Form className="h-full flex flex-col bg-white dark:bg-gray-800 shadow-xl overflow-y-scroll"
|
<Form className="h-full flex flex-col bg-white dark:bg-gray-800 shadow-xl overflow-y-scroll"
|
||||||
onSubmit={handleSubmit}>
|
onSubmit={handleSubmit}>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,17 @@ interface UpdateProps {
|
||||||
feed: Feed;
|
feed: Feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface InitialValues {
|
||||||
|
id: number;
|
||||||
|
indexer: string;
|
||||||
|
enabled: boolean;
|
||||||
|
type: FeedType;
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
api_key: string;
|
||||||
|
interval: number;
|
||||||
|
}
|
||||||
|
|
||||||
export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
const [isTesting, setIsTesting] = useState(false);
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
const [isTestSuccessful, setIsSuccessfulTest] = useState(false);
|
const [isTestSuccessful, setIsSuccessfulTest] = useState(false);
|
||||||
|
@ -26,7 +37,7 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(["feeds"]);
|
queryClient.invalidateQueries(["feeds"]);
|
||||||
toast.custom((t) => <Toast type="success" body={`${feed.name} was updated successfully`} t={t}/>);
|
toast.custom((t) => <Toast type="success" body={`${feed.name} was updated successfully`} t={t} />);
|
||||||
toggle();
|
toggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,12 +52,11 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(["feeds"]);
|
queryClient.invalidateQueries(["feeds"]);
|
||||||
toast.custom((t) => <Toast type="success" body={`${feed.name} was deleted.`} t={t}/>);
|
toast.custom((t) => <Toast type="success" body={`${feed.name} was deleted.`} t={t} />);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const deleteAction = () => {
|
const deleteAction = () => {
|
||||||
deleteMutation.mutate(feed.id);
|
deleteMutation.mutate(feed.id);
|
||||||
};
|
};
|
||||||
|
@ -85,7 +95,7 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
testFeedMutation.mutate(data as Feed);
|
testFeedMutation.mutate(data as Feed);
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues: InitialValues = {
|
||||||
id: feed.id,
|
id: feed.id,
|
||||||
indexer: feed.indexer,
|
indexer: feed.indexer,
|
||||||
enabled: feed.enabled,
|
enabled: feed.enabled,
|
||||||
|
@ -97,7 +107,7 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SlideOver
|
<SlideOver<InitialValues>
|
||||||
type="UPDATE"
|
type="UPDATE"
|
||||||
title="Feed"
|
title="Feed"
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
|
@ -112,7 +122,7 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
>
|
>
|
||||||
{(values) => (
|
{(values) => (
|
||||||
<div>
|
<div>
|
||||||
<TextFieldWide name="name" label="Name" required={true}/>
|
<TextFieldWide name="name" label="Name" required={true} />
|
||||||
|
|
||||||
<div className="space-y-4 divide-y divide-gray-200 dark:divide-gray-700">
|
<div className="space-y-4 divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
<div
|
<div
|
||||||
|
@ -131,7 +141,7 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
|
||||||
<SwitchGroupWide name="enabled" label="Enabled"/>
|
<SwitchGroupWide name="enabled" label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{componentMap[values.type]}
|
{componentMap[values.type]}
|
||||||
|
@ -150,10 +160,10 @@ function FormFieldsTorznab() {
|
||||||
help="Torznab url"
|
help="Torznab url"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PasswordFieldWide name="api_key" label="API key"/>
|
<PasswordFieldWide name="api_key" label="API key" />
|
||||||
|
|
||||||
<NumberFieldWide name="interval" label="Refresh interval"
|
<NumberFieldWide name="interval" label="Refresh interval"
|
||||||
help="Minutes. Recommended 15-30. Too low and risk ban."/>
|
help="Minutes. Recommended 15-30. Too low and risk ban." />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -167,12 +177,12 @@ function FormFieldsRSS() {
|
||||||
help="RSS url"
|
help="RSS url"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<NumberFieldWide name="interval" label="Refresh interval" help="Minutes. Recommended 15-30. Too low and risk ban."/>
|
<NumberFieldWide name="interval" label="Refresh interval" help="Minutes. Recommended 15-30. Too low and risk ban." />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentMap: componentMapType = {
|
const componentMap: componentMapType = {
|
||||||
TORZNAB: <FormFieldsTorznab/>,
|
TORZNAB: <FormFieldsTorznab />,
|
||||||
RSS: <FormFieldsRSS />
|
RSS: <FormFieldsRSS />
|
||||||
};
|
};
|
||||||
|
|
|
@ -394,6 +394,18 @@ interface UpdateProps {
|
||||||
notification: Notification;
|
notification: Notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface InitialValues {
|
||||||
|
id: number;
|
||||||
|
enabled: boolean;
|
||||||
|
type: NotificationType;
|
||||||
|
name: string;
|
||||||
|
webhook?: string;
|
||||||
|
token?: string;
|
||||||
|
api_key?: string;
|
||||||
|
channel?: string;
|
||||||
|
events: NotificationEvent[];
|
||||||
|
}
|
||||||
|
|
||||||
export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateProps) {
|
export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateProps) {
|
||||||
const mutation = useMutation(
|
const mutation = useMutation(
|
||||||
(notification: Notification) => APIClient.notifications.update(notification),
|
(notification: Notification) => APIClient.notifications.update(notification),
|
||||||
|
@ -437,7 +449,7 @@ export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateP
|
||||||
testMutation.mutate(data as Notification);
|
testMutation.mutate(data as Notification);
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues: InitialValues = {
|
||||||
id: notification.id,
|
id: notification.id,
|
||||||
enabled: notification.enabled,
|
enabled: notification.enabled,
|
||||||
type: notification.type,
|
type: notification.type,
|
||||||
|
@ -450,7 +462,7 @@ export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateP
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SlideOver
|
<SlideOver<InitialValues>
|
||||||
type="UPDATE"
|
type="UPDATE"
|
||||||
title="Notification"
|
title="Notification"
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
|
|
|
@ -62,6 +62,7 @@ export default function Base() {
|
||||||
"transition-colors duration-200",
|
"transition-colors duration-200",
|
||||||
isActive ? "text-black dark:text-gray-50 font-bold" : "text-gray-600 dark:text-gray-500"
|
isActive ? "text-black dark:text-gray-50 font-bold" : "text-gray-600 dark:text-gray-500"
|
||||||
)}
|
)}
|
||||||
|
end={item.path === "/"}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue