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:
stacksmash76 2022-09-23 19:03:00 +02:00 committed by GitHub
parent 8a782a5cab
commit 553320bf1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 35 deletions

View file

@ -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">;

View file

@ -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}>

View file

@ -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 />
}; };

View file

@ -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}

View file

@ -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>