132 lines
5.5 KiB
TypeScript
132 lines
5.5 KiB
TypeScript
import { useEffect, useMemo, useState } from "react";
|
|
import {
|
|
Accordion,
|
|
AccordionHeader,
|
|
AccordionItem,
|
|
AccordionPanel,
|
|
Field,
|
|
Input,
|
|
Text,
|
|
} from "@fluentui/react-components";
|
|
import type { ActionConfig, ActionConfigUpdate } from "../../types/config";
|
|
import { useAutoSave } from "../../hooks/useAutoSave";
|
|
import { AutoSaveIndicator } from "./AutoSaveIndicator";
|
|
import { useConfigStyles } from "./configStyles";
|
|
import { CommandField } from "./CommandField";
|
|
import { KVEditor } from "./KVEditor";
|
|
|
|
interface ActionFormEditorProps {
|
|
config: ActionConfig;
|
|
onSave: (update: ActionConfigUpdate) => Promise<void>;
|
|
}
|
|
|
|
export function ActionFormEditor({ config, onSave }: ActionFormEditorProps): React.JSX.Element {
|
|
const styles = useConfigStyles();
|
|
const [before, setBefore] = useState(config.before ?? "");
|
|
const [after, setAfter] = useState(config.after ?? "");
|
|
const [actionstart, setActionstart] = useState(config.actionstart ?? "");
|
|
const [actionstop, setActionstop] = useState(config.actionstop ?? "");
|
|
const [actioncheck, setActioncheck] = useState(config.actioncheck ?? "");
|
|
const [actionban, setActionban] = useState(config.actionban ?? "");
|
|
const [actionunban, setActionunban] = useState(config.actionunban ?? "");
|
|
const [actionflush, setActionflush] = useState(config.actionflush ?? "");
|
|
const [definitionVars, setDefinitionVars] = useState<Record<string, string>>(config.definition_vars);
|
|
const [initVars, setInitVars] = useState<Record<string, string>>(config.init_vars);
|
|
|
|
useEffect(() => {
|
|
setBefore(config.before ?? "");
|
|
setAfter(config.after ?? "");
|
|
setActionstart(config.actionstart ?? "");
|
|
setActionstop(config.actionstop ?? "");
|
|
setActioncheck(config.actioncheck ?? "");
|
|
setActionban(config.actionban ?? "");
|
|
setActionunban(config.actionunban ?? "");
|
|
setActionflush(config.actionflush ?? "");
|
|
setDefinitionVars(config.definition_vars);
|
|
setInitVars(config.init_vars);
|
|
}, [config]);
|
|
|
|
const autoSavePayload = useMemo<ActionConfigUpdate>(() => ({
|
|
before: before.trim() || null,
|
|
after: after.trim() || null,
|
|
actionstart: actionstart.trim() || null,
|
|
actionstop: actionstop.trim() || null,
|
|
actioncheck: actioncheck.trim() || null,
|
|
actionban: actionban.trim() || null,
|
|
actionunban: actionunban.trim() || null,
|
|
actionflush: actionflush.trim() || null,
|
|
definition_vars: definitionVars,
|
|
init_vars: initVars,
|
|
}), [after, actionban, actioncheck, actionflush, actionstart, actionstop, actionunban, before, definitionVars, initVars]);
|
|
|
|
const { status: saveStatus, errorText: saveErrorText, retry: retrySave } = useAutoSave(autoSavePayload, onSave);
|
|
const defVarCount = Object.keys(definitionVars).length;
|
|
const initVarCount = Object.keys(initVars).length;
|
|
|
|
return (
|
|
<div>
|
|
<div className={styles.buttonRow} style={{ marginBottom: 8 }}>
|
|
<Text size={500} weight="semibold">{config.filename}</Text>
|
|
<AutoSaveIndicator status={saveStatus} errorText={saveErrorText} onRetry={retrySave} />
|
|
</div>
|
|
|
|
<Accordion multiple collapsible defaultOpenItems={["lifecycle"]}>
|
|
<AccordionItem value="includes" className={styles.accordionItem}>
|
|
<AccordionHeader>Includes</AccordionHeader>
|
|
<AccordionPanel>
|
|
<div className={styles.sectionCard}>
|
|
<Field label="before">
|
|
<Input
|
|
value={before}
|
|
onChange={(_e, d) => { setBefore(d.value); }}
|
|
placeholder="e.g. iptables-common.conf"
|
|
className={styles.codeInput}
|
|
/>
|
|
</Field>
|
|
<Field label="after">
|
|
<Input
|
|
value={after}
|
|
onChange={(_e, d) => { setAfter(d.value); }}
|
|
className={styles.codeInput}
|
|
/>
|
|
</Field>
|
|
</div>
|
|
</AccordionPanel>
|
|
</AccordionItem>
|
|
|
|
<AccordionItem value="lifecycle" className={styles.accordionItem}>
|
|
<AccordionHeader>Lifecycle commands</AccordionHeader>
|
|
<AccordionPanel>
|
|
<div className={styles.sectionCard}>
|
|
<CommandField label="actionstart" value={actionstart} onChange={setActionstart} />
|
|
<CommandField label="actionstop" value={actionstop} onChange={setActionstop} />
|
|
<CommandField label="actioncheck" value={actioncheck} onChange={setActioncheck} />
|
|
<CommandField label="actionban" value={actionban} onChange={setActionban} />
|
|
<CommandField label="actionunban" value={actionunban} onChange={setActionunban} />
|
|
<CommandField label="actionflush" value={actionflush} onChange={setActionflush} />
|
|
</div>
|
|
</AccordionPanel>
|
|
</AccordionItem>
|
|
|
|
<AccordionItem value="definition_vars" className={styles.accordionItem}>
|
|
<AccordionHeader>{`Definition variables (${String(defVarCount)})`}</AccordionHeader>
|
|
<AccordionPanel>
|
|
<div className={styles.sectionCard}>
|
|
<KVEditor entries={definitionVars} onChange={setDefinitionVars} />
|
|
</div>
|
|
</AccordionPanel>
|
|
</AccordionItem>
|
|
|
|
<AccordionItem value="init_vars" className={styles.accordionItem}>
|
|
<AccordionHeader>{`Init variables (${String(initVarCount)})`}</AccordionHeader>
|
|
<AccordionPanel>
|
|
<div className={styles.sectionCard}>
|
|
<KVEditor entries={initVars} onChange={setInitVars} />
|
|
</div>
|
|
</AccordionPanel>
|
|
</AccordionItem>
|
|
</Accordion>
|
|
</div>
|
|
);
|
|
}
|