fix(system): preserve MQTT interval draft editing
This commit is contained in:
@@ -18,6 +18,11 @@ import {
|
||||
type ComputeContourDraft,
|
||||
type ComputeContourPlatform,
|
||||
} from "../../core/system/computeContours";
|
||||
import {
|
||||
DEFAULT_TELEMETRY_POLL_INTERVAL_SECONDS,
|
||||
parseTelemetryPollIntervalDraft,
|
||||
resolveTelemetryPollIntervalDraft,
|
||||
} from "../../core/system/telemetryPollInterval";
|
||||
|
||||
interface ComputeContourSettingsWindowProps {
|
||||
open: boolean;
|
||||
@@ -51,7 +56,7 @@ function emptyDraft(): ComputeContourDraft {
|
||||
ssh_port: 22,
|
||||
mqtt_host: "127.0.0.1",
|
||||
mqtt_port: 1883,
|
||||
telemetry_poll_interval_seconds: 3,
|
||||
telemetry_poll_interval_seconds: DEFAULT_TELEMETRY_POLL_INTERVAL_SECONDS,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -79,6 +84,9 @@ export function ComputeContourSettingsWindow({
|
||||
onUpdate,
|
||||
}: ComputeContourSettingsWindowProps) {
|
||||
const [draft, setDraft] = useState<ComputeContourDraft>(() => draftFromContour(contour));
|
||||
const [telemetryPollIntervalDraft, setTelemetryPollIntervalDraft] = useState(
|
||||
() => String(draftFromContour(contour).telemetry_poll_interval_seconds),
|
||||
);
|
||||
const [activeSection, setActiveSection] = useState<"connection" | "agent">("connection");
|
||||
const [install, setInstall] = useState<ComputeContourAgentInstall | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
@@ -86,7 +94,9 @@ export function ComputeContourSettingsWindow({
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
setDraft(draftFromContour(mode === "edit" ? contour : null));
|
||||
const nextDraft = draftFromContour(mode === "edit" ? contour : null);
|
||||
setDraft(nextDraft);
|
||||
setTelemetryPollIntervalDraft(String(nextDraft.telemetry_poll_interval_seconds));
|
||||
setActiveSection("connection");
|
||||
setInstall(null);
|
||||
setError(null);
|
||||
@@ -107,6 +117,11 @@ export function ComputeContourSettingsWindow({
|
||||
return () => controller.abort();
|
||||
}, [contour, mode, open]);
|
||||
|
||||
const telemetryPollIntervalSeconds = useMemo(
|
||||
() => parseTelemetryPollIntervalDraft(telemetryPollIntervalDraft),
|
||||
[telemetryPollIntervalDraft],
|
||||
);
|
||||
|
||||
const valid = useMemo(() => (
|
||||
Boolean(draft.display_name.trim())
|
||||
&& Boolean(draft.expected_node_id.trim())
|
||||
@@ -114,20 +129,39 @@ export function ComputeContourSettingsWindow({
|
||||
&& draft.ssh_port > 0
|
||||
&& Number.isInteger(draft.mqtt_port)
|
||||
&& draft.mqtt_port > 0
|
||||
&& Number.isInteger(draft.telemetry_poll_interval_seconds)
|
||||
&& draft.telemetry_poll_interval_seconds >= 1
|
||||
&& draft.telemetry_poll_interval_seconds <= 60
|
||||
), [draft]);
|
||||
&& telemetryPollIntervalSeconds !== null
|
||||
), [draft, telemetryPollIntervalSeconds]);
|
||||
|
||||
const commitTelemetryPollInterval = () => {
|
||||
const resolution = resolveTelemetryPollIntervalDraft(
|
||||
telemetryPollIntervalDraft,
|
||||
draft.telemetry_poll_interval_seconds,
|
||||
);
|
||||
setTelemetryPollIntervalDraft(resolution.draft);
|
||||
if (!resolution.accepted) return;
|
||||
setDraft((current) => (
|
||||
current.telemetry_poll_interval_seconds === resolution.seconds
|
||||
? current
|
||||
: {
|
||||
...current,
|
||||
telemetry_poll_interval_seconds: resolution.seconds,
|
||||
}
|
||||
));
|
||||
};
|
||||
|
||||
const save = async () => {
|
||||
if (!valid || busy) return;
|
||||
if (!valid || busy || telemetryPollIntervalSeconds === null) return;
|
||||
const committedDraft = {
|
||||
...draft,
|
||||
telemetry_poll_interval_seconds: telemetryPollIntervalSeconds,
|
||||
};
|
||||
setBusy(true);
|
||||
setError(null);
|
||||
try {
|
||||
if (mode === "edit" && contour) {
|
||||
await onUpdate(contour, draft);
|
||||
await onUpdate(contour, committedDraft);
|
||||
} else {
|
||||
await onCreate(draft);
|
||||
await onCreate(committedDraft);
|
||||
}
|
||||
onClose();
|
||||
} catch (reason) {
|
||||
@@ -241,14 +275,26 @@ export function ComputeContourSettingsWindow({
|
||||
<TextField
|
||||
label="Интервал MQTT"
|
||||
hint="1–60 с"
|
||||
type="number"
|
||||
min={1}
|
||||
max={60}
|
||||
value={String(draft.telemetry_poll_interval_seconds)}
|
||||
onChange={(event) => setDraft((current) => ({
|
||||
...current,
|
||||
telemetry_poll_interval_seconds: Number(event.currentTarget.value),
|
||||
}))}
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
autoComplete="off"
|
||||
aria-invalid={telemetryPollIntervalSeconds === null}
|
||||
value={telemetryPollIntervalDraft}
|
||||
onChange={(event) => setTelemetryPollIntervalDraft(event.currentTarget.value)}
|
||||
onBlur={commitTelemetryPollInterval}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
commitTelemetryPollInterval();
|
||||
} else if (event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setTelemetryPollIntervalDraft(
|
||||
String(draft.telemetry_poll_interval_seconds),
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{draft.telemetry_mode === "legacy-ssh" ? (
|
||||
<TextField
|
||||
|
||||
Reference in New Issue
Block a user