mirror of https://github.com/jetkvm/kvm.git
222 lines
5.9 KiB
TypeScript
222 lines
5.9 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
|
|
import { Button } from "@components/Button";
|
|
import { SelectMenuBasic } from "@components/SelectMenuBasic";
|
|
|
|
import { useJsonRpc } from "../hooks/useJsonRpc";
|
|
import notifications from "../notifications";
|
|
|
|
import { InputFieldWithLabel } from "./InputField";
|
|
|
|
|
|
export interface JigglerConfig {
|
|
inactivity_limit_seconds: number;
|
|
jitter_percentage: number;
|
|
schedule_cron_tab: string;
|
|
}
|
|
|
|
const jigglerCrontabConfigs = [
|
|
{
|
|
label: "Every 20 seconds",
|
|
value: "*/20 * * * * *",
|
|
},
|
|
{
|
|
label: "Every 40 seconds",
|
|
value: "*/40 * * * * *",
|
|
},
|
|
{
|
|
label: "Every 1 minute",
|
|
value: "0 * * * * *",
|
|
},
|
|
{
|
|
label: "Every 3 minutes",
|
|
value: "0 */3 * * * *",
|
|
},
|
|
];
|
|
|
|
const jigglerJitterConfigs = [
|
|
{
|
|
label: "No Jitter",
|
|
value: "0",
|
|
},
|
|
{
|
|
label: "10%",
|
|
value: "20",
|
|
},
|
|
{
|
|
label: "25%",
|
|
value: "25",
|
|
},
|
|
{
|
|
label: "50%",
|
|
value: "50",
|
|
},
|
|
];
|
|
|
|
const jigglerInactivityConfigs = [
|
|
{
|
|
label: "20 Seconds",
|
|
value: "20",
|
|
},
|
|
{
|
|
label: "40 Seconds",
|
|
value: "40",
|
|
},
|
|
{
|
|
label: "1 Minute",
|
|
value: "60",
|
|
},
|
|
{
|
|
label: "3 Minutes",
|
|
value: "180",
|
|
},
|
|
];
|
|
|
|
export function JigglerSetting() {
|
|
const [send] = useJsonRpc();
|
|
const [loading, setLoading] = useState(false);
|
|
const [jitterPercentage, setJitterPercentage] = useState("");
|
|
const [scheduleCronTab, setScheduleCronTab] = useState("");
|
|
|
|
const [jigglerConfigState, setJigglerConfigState] = useState<JigglerConfig>({
|
|
inactivity_limit_seconds: 20,
|
|
jitter_percentage: 0,
|
|
schedule_cron_tab: "*/20 * * * * *"
|
|
});
|
|
|
|
const syncJigglerConfig = useCallback(() => {
|
|
send("getJigglerConfig", {}, resp => {
|
|
if ("error" in resp) return;
|
|
const result = resp.result as JigglerConfig;
|
|
setJigglerConfigState(result);
|
|
|
|
const jitterPercentage = jigglerJitterConfigs.map(u => u.value).includes(result.jitter_percentage.toString())
|
|
? result.jitter_percentage.toString()
|
|
: "custom";
|
|
setJitterPercentage(jitterPercentage)
|
|
|
|
const scheduleCronTab = jigglerCrontabConfigs.map(u => u.value).includes(result.schedule_cron_tab)
|
|
? result.schedule_cron_tab
|
|
: "custom";
|
|
setScheduleCronTab(scheduleCronTab)
|
|
});
|
|
}, [send]);
|
|
|
|
useEffect(() => {
|
|
syncJigglerConfig()
|
|
}, [send, syncJigglerConfig]);
|
|
|
|
const handleJigglerInactivityLimitSecondsChange = (value: string) => {
|
|
setJigglerConfigState({ ...jigglerConfigState, inactivity_limit_seconds: Number(value) });
|
|
};
|
|
|
|
const handleJigglerJitterPercentageChange = (value: string) => {
|
|
setJigglerConfigState({ ...jigglerConfigState, jitter_percentage: Number(value) });
|
|
};
|
|
|
|
const handleJigglerScheduleCronTabChange = (value: string) => {
|
|
setJigglerConfigState({ ...jigglerConfigState, schedule_cron_tab: value });
|
|
};
|
|
|
|
const handleJigglerConfigSave = useCallback(
|
|
(jigglerConfig: JigglerConfig) => {
|
|
setLoading(true);
|
|
send("setJigglerConfig", { jigglerConfig }, async resp => {
|
|
if ("error" in resp) {
|
|
notifications.error(
|
|
`Failed to set jiggler config: ${resp.error.data || "Unknown error"}`,
|
|
);
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
setLoading(false);
|
|
notifications.success(
|
|
`Jiggler Config successfully updated`,
|
|
);
|
|
syncJigglerConfig();
|
|
});
|
|
},
|
|
[send, syncJigglerConfig],
|
|
);
|
|
|
|
return (
|
|
<div className="">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<SelectMenuBasic
|
|
size="SM"
|
|
label="Schedule"
|
|
className="max-w-[192px]"
|
|
value={scheduleCronTab}
|
|
fullWidth
|
|
onChange={e => {
|
|
setScheduleCronTab(e.target.value);
|
|
if (e.target.value != "custom") {
|
|
handleJigglerScheduleCronTabChange(e.target.value);
|
|
}
|
|
}}
|
|
options={[...jigglerCrontabConfigs, {value: "custom", label: "Custom"}]}
|
|
/>
|
|
{scheduleCronTab === "custom" && (
|
|
<InputFieldWithLabel
|
|
required
|
|
label="Jiggler Crontab"
|
|
placeholder="*/20 * * * * *"
|
|
defaultValue={jigglerConfigState.schedule_cron_tab}
|
|
onChange={e => handleJigglerScheduleCronTabChange(e.target.value)}
|
|
/>
|
|
)}
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<SelectMenuBasic
|
|
size="SM"
|
|
label="Jitter Percentage"
|
|
className="max-w-[192px]"
|
|
value={jitterPercentage}
|
|
fullWidth
|
|
onChange={e => {
|
|
setJitterPercentage(e.target.value);
|
|
if (e.target.value != "custom") {
|
|
handleJigglerJitterPercentageChange(e.target.value)
|
|
}
|
|
}}
|
|
options={[...jigglerJitterConfigs, {value: "custom", label: "Custom"}]}
|
|
/>
|
|
{jitterPercentage === "custom" && (
|
|
<InputFieldWithLabel
|
|
required
|
|
label="Jitter Percentage"
|
|
placeholder="25"
|
|
defaultValue={jigglerConfigState.jitter_percentage}
|
|
type="number"
|
|
min="1"
|
|
max="100"
|
|
onChange={e => handleJigglerJitterPercentageChange(e.target.value)}
|
|
/>
|
|
)}
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<SelectMenuBasic
|
|
size="SM"
|
|
label="Inactivity Limit Seconds"
|
|
className="max-w-[192px]"
|
|
value={jigglerConfigState.inactivity_limit_seconds}
|
|
fullWidth
|
|
onChange={e => {
|
|
handleJigglerInactivityLimitSecondsChange(e.target.value);
|
|
}}
|
|
options={[...jigglerInactivityConfigs]}
|
|
/>
|
|
</div>
|
|
<div className="mt-6 flex gap-x-2">
|
|
<Button
|
|
loading={loading}
|
|
size="SM"
|
|
theme="primary"
|
|
text="Update Jiggler Config"
|
|
onClick={() => handleJigglerConfigSave(jigglerConfigState)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|