Update setting is working

Adjust the ui

Adjust description
This commit is contained in:
Owen
2026-05-21 16:21:23 -07:00
parent 6d4afd0953
commit 4530aac4f3
5 changed files with 85 additions and 71 deletions

View File

@@ -1601,16 +1601,15 @@
"contents": "Contents",
"parsedContents": "Parsed Contents (Read Only)",
"enableDockerSocket": "Enable Docker Blueprint",
"enableDockerSocketDescription": "Enable Docker Socket label scraping for blueprint labels. Socket path must be provided to Newt. Read about how this works in <docsLink>the documentation</docsLink>.",
"newtAutoUpdate": "Enable Newt Auto-Update",
"newtAutoUpdateDescription": "When enabled, Newt clients will automatically update to the latest version when a new release is available.",
"newtAutoUpdateDisabledDescription": "This feature requires a valid license (Enterprise) or active subscription (SaaS)",
"siteAutoUpdate": "Newt Auto-Update",
"enableDockerSocketDescription": "Enable Docker Socket label scraping for blueprint labels. Socket path must be provided to the site connector. Read about how this works in <docsLink>the documentation</docsLink>.",
"newtAutoUpdate": "Enable Site Auto-Update",
"newtAutoUpdateDescription": "When enabled, site connectors will automatically update to the latest version when a new release is available.",
"siteAutoUpdate": "Site Auto-Update",
"siteAutoUpdateLabel": "Enable Auto-Update",
"siteAutoUpdateDescription": "Control whether this site's Newt client automatically updates. When not overriding, the organization default is used.",
"siteAutoUpdateDescription": "Control whether this site's connector automatically downloads the latest version.",
"siteAutoUpdateOrgDefault": "Organization default: {state}",
"siteAutoUpdateOverriding": "Overriding organization setting",
"siteAutoUpdateResetToOrg": "Reset to organization default",
"siteAutoUpdateResetToOrg": "Reset to Organization Default",
"siteAutoUpdateEnabled": "enabled",
"siteAutoUpdateDisabled": "disabled",
"viewDockerContainers": "View Docker Containers",

View File

@@ -217,6 +217,7 @@ function GeneralSectionForm({ org }: SectionFormProps) {
title: t("orgUpdated"),
description: t("orgUpdatedDescription")
});
router.refresh();
} catch (e) {
toast({
@@ -260,6 +261,9 @@ function GeneralSectionForm({ org }: SectionFormProps) {
)}
/>
<PaidFeaturesAlert
tiers={tierMatrix.newtAutoUpdate}
/>
<FormField
control={form.control}
name="settingsEnableGlobalNewtAutoUpdate"
@@ -271,17 +275,11 @@ function GeneralSectionForm({ org }: SectionFormProps) {
label={t("newtAutoUpdate")}
checked={field.value}
onCheckedChange={field.onChange}
disabled={
!hasAutoUpdateFeature
}
disabled={!hasAutoUpdateFeature}
/>
</FormControl>
<FormDescription>
{hasAutoUpdateFeature
? t("newtAutoUpdateDescription")
: t(
"newtAutoUpdateDisabledDescription"
)}
{t("newtAutoUpdateDescription")}
</FormDescription>
<FormMessage />
</FormItem>

View File

@@ -40,6 +40,7 @@ import { useOrgContext } from "@app/hooks/useOrgContext";
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { tierMatrix, TierFeature } from "@server/lib/billing/tierMatrix";
import { Button as ButtonUI } from "@/components/ui/button";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
const GeneralFormSchema = z.object({
name: z.string().nonempty("Name is required"),
@@ -70,8 +71,7 @@ export default function GeneralPage() {
null
);
const orgAutoUpdate =
org.org.settingsEnableGlobalNewtAutoUpdate ?? false;
const orgAutoUpdate = org.org.settingsEnableGlobalNewtAutoUpdate ?? false;
const form = useForm({
resolver: zodResolver(GeneralFormSchema),
@@ -221,7 +221,9 @@ export default function GeneralPage() {
{t.rich(
"enableDockerSocketDescription",
{
docsLink: (chunks) => (
docsLink: (
chunks
) => (
<a
href="https://docs.pangolin.net/manage/sites/configure-site#docker-socket-integration"
target="_blank"
@@ -240,53 +242,50 @@ export default function GeneralPage() {
/>
)}
<PaidFeaturesAlert
tiers={tierMatrix.newtAutoUpdate}
/>
{site && site.type === "newt" && (
<FormField
control={form.control}
name="autoUpdateEnabled"
render={({ field }) => {
const isOverriding =
form.watch(
"autoUpdateOverrideOrg"
);
const isOverriding = form.watch(
"autoUpdateOverrideOrg"
);
return (
<FormItem>
<FormControl>
<SwitchInput
id="auto-update-enabled"
label={t(
"siteAutoUpdateLabel"
)}
checked={
field.value
}
onCheckedChange={(checked) => {
field.onChange(
<div className="flex items-center gap-3">
<SwitchInput
id="auto-update-enabled"
label={t(
"siteAutoUpdateLabel"
)}
checked={
field.value
}
onCheckedChange={(
checked
);
form.setValue(
"autoUpdateOverrideOrg",
true
);
}}
disabled={
!hasAutoUpdateFeature
}
/>
</FormControl>
<FormDescription>
{isOverriding ? (
<span className="flex items-center gap-2">
<span>
{t(
"siteAutoUpdateOverriding"
)}
</span>
) => {
field.onChange(
checked
);
form.setValue(
"autoUpdateOverrideOrg",
true
);
}}
disabled={
!hasAutoUpdateFeature
}
/>
{isOverriding && (
<ButtonUI
type="button"
variant="link"
size="sm"
className="h-auto p-0 text-xs"
className="h-auto p-0 pb-2 text-xs"
onClick={() => {
form.setValue(
"autoUpdateOverrideOrg",
@@ -302,20 +301,12 @@ export default function GeneralPage() {
"siteAutoUpdateResetToOrg"
)}
</ButtonUI>
</span>
) : (
t(
"siteAutoUpdateOrgDefault",
{
state: orgAutoUpdate
? t(
"siteAutoUpdateEnabled"
)
: t(
"siteAutoUpdateDisabled"
)
}
)
)}
</div>
</FormControl>
<FormDescription>
{t(
"siteAutoUpdateDescription"
)}
</FormDescription>
<FormMessage />

View File

@@ -1,6 +1,8 @@
import SiteProvider from "@app/providers/SiteProvider";
import OrgProvider from "@app/providers/OrgProvider";
import { internal } from "@app/lib/api";
import { GetSiteResponse } from "@server/routers/site";
import { GetOrgResponse } from "@server/routers/org";
import { AxiosResponse } from "axios";
import { redirect } from "next/navigation";
import { authCookieHeader } from "@app/lib/api/cookies";
@@ -35,6 +37,17 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
redirect(`/${params.orgId}/settings/sites`);
}
let org = null;
try {
const res = await internal.get<AxiosResponse<GetOrgResponse>>(
`/org/${params.orgId}`,
await authCookieHeader()
);
org = res.data.data;
} catch {
redirect(`/${params.orgId}/settings/sites`);
}
const t = await getTranslations();
const navItems = [
@@ -64,10 +77,14 @@ export default async function SettingsLayout(props: SettingsLayoutProps) {
/>
<SiteProvider site={site}>
<div className="space-y-4">
<SiteInfoCard />
<HorizontalTabs items={navItems}>{children}</HorizontalTabs>
</div>
<OrgProvider org={org}>
<div className="space-y-4">
<SiteInfoCard />
<HorizontalTabs items={navItems}>
{children}
</HorizontalTabs>
</div>
</OrgProvider>
</SiteProvider>
</>
);

View File

@@ -45,7 +45,16 @@ export function SwitchInput({
return (
<div>
<div className="flex items-center space-x-2 mb-2">
{label && <Label htmlFor={id}>{label}</Label>}
{label && (
<Label
htmlFor={id}
className={
disabled ? "opacity-50 cursor-not-allowed" : ""
}
>
{label}
</Label>
)}
<Switch
id={id}
checked={checked}