103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
import { useCallback, useState } from "react";
|
|
import {
|
|
Button,
|
|
Dialog,
|
|
DialogActions,
|
|
DialogBody,
|
|
DialogContent,
|
|
DialogSurface,
|
|
DialogTitle,
|
|
Field,
|
|
Input,
|
|
MessageBar,
|
|
MessageBarBody,
|
|
Switch,
|
|
} from "@fluentui/react-components";
|
|
|
|
interface SourceFormValues {
|
|
name: string;
|
|
url: string;
|
|
enabled: boolean;
|
|
}
|
|
|
|
interface SourceFormDialogProps {
|
|
open: boolean;
|
|
mode: "add" | "edit";
|
|
initial: SourceFormValues;
|
|
saving: boolean;
|
|
error: string | null;
|
|
onClose: () => void;
|
|
onSubmit: (values: SourceFormValues) => void;
|
|
}
|
|
|
|
export function SourceFormDialog({
|
|
open,
|
|
mode,
|
|
initial,
|
|
saving,
|
|
error,
|
|
onClose,
|
|
onSubmit,
|
|
}: SourceFormDialogProps): React.JSX.Element {
|
|
const [values, setValues] = useState<SourceFormValues>(initial);
|
|
|
|
const handleOpen = useCallback((): void => {
|
|
setValues(initial);
|
|
}, [initial]);
|
|
|
|
return (
|
|
<Dialog
|
|
open={open}
|
|
onOpenChange={(_ev, data) => {
|
|
if (!data.open) onClose();
|
|
}}
|
|
>
|
|
<DialogSurface onAnimationEnd={open ? handleOpen : undefined}>
|
|
<DialogBody>
|
|
<DialogTitle>{mode === "add" ? "Add Blocklist Source" : "Edit Blocklist Source"}</DialogTitle>
|
|
<DialogContent>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
|
|
{error && (
|
|
<MessageBar intent="error">
|
|
<MessageBarBody>{error}</MessageBarBody>
|
|
</MessageBar>
|
|
)}
|
|
<Field label="Name" required>
|
|
<Input
|
|
value={values.name}
|
|
onChange={(_ev, d) => { setValues((p) => ({ ...p, name: d.value })); }}
|
|
placeholder="e.g. Blocklist.de — All"
|
|
/>
|
|
</Field>
|
|
<Field label="URL" required>
|
|
<Input
|
|
value={values.url}
|
|
onChange={(_ev, d) => { setValues((p) => ({ ...p, url: d.value })); }}
|
|
placeholder="https://lists.blocklist.de/lists/all.txt"
|
|
/>
|
|
</Field>
|
|
<Switch
|
|
label="Enabled"
|
|
checked={values.enabled}
|
|
onChange={(_ev, d) => { setValues((p) => ({ ...p, enabled: d.checked })); }}
|
|
/>
|
|
</div>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button appearance="secondary" onClick={onClose} disabled={saving}>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
appearance="primary"
|
|
disabled={saving || !values.name.trim() || !values.url.trim()}
|
|
onClick={() => { onSubmit(values); }}
|
|
>
|
|
{saving ? "Saving…" : mode === "add" ? "Add" : "Save"}
|
|
</Button>
|
|
</DialogActions>
|
|
</DialogBody>
|
|
</DialogSurface>
|
|
</Dialog>
|
|
);
|
|
}
|