Add auto update setting (#519)

This commit is contained in:
Eduard Gert
2025-12-29 12:38:50 +01:00
committed by GitHub
parent 8d6b617cbd
commit b058e66e32
2 changed files with 138 additions and 2 deletions

View File

@@ -22,6 +22,7 @@ export interface Account {
dns_domain: string;
network_range?: string;
lazy_connection_enabled: boolean;
auto_update_version: string;
};
onboarding?: AccountOnboarding;
}

View File

@@ -1,16 +1,27 @@
import Breadcrumbs from "@components/Breadcrumbs";
import Button from "@components/Button";
import FancyToggleSwitch from "@components/FancyToggleSwitch";
import HelpText from "@components/HelpText";
import InlineLink from "@components/InlineLink";
import { Input } from "@components/Input";
import { Label } from "@components/Label";
import { notify } from "@components/Notification";
import {
SelectDropdown,
SelectOption,
} from "@components/select/SelectDropdown";
import { useHasChanges } from "@hooks/useHasChanges";
import * as Tabs from "@radix-ui/react-tabs";
import { useApiCall } from "@utils/api";
import { validator } from "@utils/helpers";
import {
ClockFadingIcon,
ExternalLinkIcon,
FlaskConicalIcon,
MonitorSmartphoneIcon,
RefreshCcw,
} from "lucide-react";
import React, { useState } from "react";
import React, { useMemo, useState } from "react";
import { useSWRConfig } from "swr";
import SettingsIcon from "@/assets/icons/SettingsIcon";
import { usePermissions } from "@/contexts/PermissionsProvider";
@@ -20,6 +31,21 @@ type Props = {
account: Account;
};
const latestOrCustomVersion = [
{
label: "Disabled",
value: "disabled",
},
{
label: "Latest Version",
value: "latest",
},
{
label: "Custom Version",
value: "custom",
},
] as SelectOption[];
export default function ClientSettingsTab({ account }: Readonly<Props>) {
const { permission } = usePermissions();
@@ -30,6 +56,77 @@ export default function ClientSettingsTab({ account }: Readonly<Props>) {
account.settings?.lazy_connection_enabled ?? false,
);
const autoUpdateSetting = account.settings?.auto_update_version;
const isAutoUpdateEnabled =
!!autoUpdateSetting && autoUpdateSetting !== "disabled";
const isCustomVersion = validator.isValidVersion(autoUpdateSetting);
const [autoUpdateMethod, setAutoUpdateMethod] = useState(
isAutoUpdateEnabled ? (isCustomVersion ? "custom" : "latest") : "disabled",
);
const [autoUpdateCustomVersion, setAutoUpdateCustomVersion] = useState(
isCustomVersion ? autoUpdateSetting : "",
);
const { hasChanges, updateRef } = useHasChanges([
autoUpdateMethod,
autoUpdateCustomVersion,
]);
const handleUpdateMethodChange = (value: string) => {
setAutoUpdateMethod(value);
if (value === "disabled" || value === "latest") {
setAutoUpdateCustomVersion("");
}
};
const versionError = useMemo(() => {
const msg = "Please enter a valid version, e.g., 0.2, 0.2.0, 0.2.0-alpha.1";
if (autoUpdateCustomVersion == "") return "";
if (autoUpdateCustomVersion == "-") return "";
const validSemver = validator.isValidVersion(autoUpdateCustomVersion);
if (!validSemver) return msg;
return "";
}, [autoUpdateCustomVersion]);
const canSaveCustomVersion =
autoUpdateCustomVersion !== "" &&
autoUpdateMethod === "custom" &&
versionError === "";
const isSaveButtonDisabled = useMemo(() => {
return (
!hasChanges ||
!permission.settings.update ||
(autoUpdateMethod === "custom" && !canSaveCustomVersion)
);
}, [
hasChanges,
permission.settings.update,
autoUpdateMethod,
canSaveCustomVersion,
]);
const saveChanges = async () => {
notify({
title: "Client Settings",
description: `Client settings successfully updated.`,
promise: saveRequest
.put({
id: account.id,
settings: {
...account.settings,
auto_update_version: autoUpdateCustomVersion || autoUpdateMethod,
},
})
.then(() => {
mutate("/accounts");
updateRef([autoUpdateMethod, autoUpdateCustomVersion]);
}),
loadingMessage: "Updating client settings...",
});
};
const toggleLazyConnection = async (toggle: boolean) => {
notify({
title: "Lazy Connections",
@@ -70,10 +167,48 @@ export default function ClientSettingsTab({ account }: Readonly<Props>) {
</Breadcrumbs>
<div className={"flex items-start justify-between"}>
<h1>Clients</h1>
<Button
variant={"primary"}
disabled={isSaveButtonDisabled}
onClick={saveChanges}
data-cy={"save-clients-settings"}
>
Save Changes
</Button>
</div>
<div className={"flex flex-col gap-6 w-full mt-8"}>
<div className={"mt-0"}>
<div className={"flex flex-col relative"}>
<Label>
<RefreshCcw size={15} />
Automatic Updates
</Label>
<HelpText>
Select how NetBird clients handle automatic updates by choosing
the latest version, a custom version, or disabling updates
altogether.
</HelpText>
<div className={"gap-4 items-center grid grid-cols-2"}>
<SelectDropdown
value={autoUpdateMethod}
onChange={handleUpdateMethodChange}
options={latestOrCustomVersion}
/>
<Input
value={autoUpdateCustomVersion}
customPrefix={"Version"}
placeholder={"e.g., 0.52.2"}
error={versionError}
errorTooltip={true}
disabled={autoUpdateMethod !== "custom"}
onChange={(v) => {
setAutoUpdateCustomVersion(v.target.value);
}}
/>
</div>
</div>
<div className={"mt-3"}>
<h2 className={"text-lg font-medium"}>
Experimental
<FlaskConicalIcon