bazarr/frontend/src/pages/Settings/Notifications/components.tsx

172 lines
4.4 KiB
TypeScript

import api from "@/apis/raw";
import { Selector } from "@/components";
import MutateButton from "@/components/async/MutateButton";
import { useModals, withModal } from "@/modules/modals";
import { BuildKey, useSelectorOptions } from "@/utilities";
import FormUtils from "@/utilities/form";
import {
Button,
Divider,
Group,
SimpleGrid,
Stack,
Textarea,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { isObject } from "lodash";
import { FunctionComponent, useCallback, useMemo } from "react";
import { useMutation } from "react-query";
import { Card } from "../components";
import { notificationsKey } from "../keys";
import { useSettingValue, useUpdateArray } from "../utilities/hooks";
const notificationHook = (notifications: Settings.NotificationInfo[]) => {
return notifications.map((info) => JSON.stringify(info));
};
interface Props {
selections: readonly Settings.NotificationInfo[];
payload: Settings.NotificationInfo | null;
onComplete: (info: Settings.NotificationInfo) => void;
}
const NotificationForm: FunctionComponent<Props> = ({
selections,
payload,
onComplete,
}) => {
const availableSelections = useMemo(
() => selections.filter((v) => !v.enabled || v.name === payload?.name),
[payload?.name, selections]
);
const options = useSelectorOptions(availableSelections, (v) => v.name);
const modals = useModals();
const form = useForm({
initialValues: {
selection: payload,
url: payload?.url ?? "",
},
validate: {
selection: FormUtils.validation(
isObject,
"Please select a notification provider"
),
url: FormUtils.validation(
(value) => value.trim().length !== 0,
"URL must not be empty"
),
},
});
const test = useMutation((url: string) => api.system.testNotification(url));
return (
<form
onSubmit={form.onSubmit(({ selection, url }) => {
if (selection) {
onComplete({ ...selection, enabled: true, url });
}
modals.closeSelf();
})}
>
<Stack>
<Selector
disabled={payload !== null}
{...options}
{...form.getInputProps("selection")}
></Selector>
<div hidden={form.values.selection === null}>
<Textarea
minRows={4}
placeholder="URL"
{...form.getInputProps("url")}
></Textarea>
</div>
<Divider></Divider>
<Group position="right">
<MutateButton mutation={test} args={() => form.values.url}>
Test
</MutateButton>
<Button
hidden={payload === null}
color="red"
onClick={() => {
if (payload) {
onComplete({ ...payload, enabled: false });
}
modals.closeAll();
}}
>
Remove
</Button>
<Button type="submit">Save</Button>
</Group>
</Stack>
</form>
);
};
const NotificationModal = withModal(NotificationForm, "notification-tool", {
title: "Notification",
});
export const NotificationView: FunctionComponent = () => {
const notifications = useSettingValue<Settings.NotificationInfo[]>(
notificationsKey,
{
onLoaded: (settings) => settings.notifications.providers,
onSubmit: (value) => value.map((v) => JSON.stringify(v)),
}
);
const update = useUpdateArray<Settings.NotificationInfo>(
notificationsKey,
"name"
);
const updateWrapper = useCallback(
(info: Settings.NotificationInfo) => {
update(info, notificationHook);
},
[update]
);
const modals = useModals();
const elements = useMemo(() => {
return notifications
?.filter((v) => v.enabled)
.map((payload, idx) => (
<Card
key={BuildKey(idx, payload.name)}
header={payload.name}
onClick={() =>
modals.openContextModal(NotificationModal, {
payload,
selections: notifications,
onComplete: updateWrapper,
})
}
></Card>
));
}, [modals, notifications, updateWrapper]);
return (
<SimpleGrid cols={3}>
{elements}
<Card
plus
onClick={() =>
modals.openContextModal(NotificationModal, {
payload: null,
selections: notifications ?? [],
onComplete: updateWrapper,
})
}
></Card>
</SimpleGrid>
);
};