mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-06 18:56:39 +00:00
separate maintenance section
This commit is contained in:
@@ -61,6 +61,363 @@ import {
|
|||||||
TooltipTrigger
|
TooltipTrigger
|
||||||
} from "@app/components/ui/tooltip";
|
} from "@app/components/ui/tooltip";
|
||||||
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
||||||
|
import { GetResourceResponse } from "@server/routers/resource/getResource";
|
||||||
|
import type { ResourceContextType } from "@app/contexts/resourceContext";
|
||||||
|
|
||||||
|
type MaintenanceSectionFormProps = {
|
||||||
|
resource: GetResourceResponse;
|
||||||
|
updateResource: ResourceContextType["updateResource"];
|
||||||
|
};
|
||||||
|
|
||||||
|
function MaintenanceSectionForm({
|
||||||
|
resource,
|
||||||
|
updateResource
|
||||||
|
}: MaintenanceSectionFormProps) {
|
||||||
|
const { env } = useEnvContext();
|
||||||
|
const t = useTranslations();
|
||||||
|
const api = createApiClient({ env });
|
||||||
|
const { isUnlocked } = useLicenseStatusContext();
|
||||||
|
const subscription = useSubscriptionStatusContext();
|
||||||
|
|
||||||
|
const MaintenanceFormSchema = z.object({
|
||||||
|
maintenanceModeEnabled: z.boolean().optional(),
|
||||||
|
maintenanceModeType: z.enum(["forced", "automatic"]).optional(),
|
||||||
|
maintenanceTitle: z.string().max(255).optional(),
|
||||||
|
maintenanceMessage: z.string().max(2000).optional(),
|
||||||
|
maintenanceEstimatedTime: z.string().max(100).optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
const maintenanceForm = useForm({
|
||||||
|
resolver: zodResolver(MaintenanceFormSchema),
|
||||||
|
defaultValues: {
|
||||||
|
maintenanceModeEnabled: resource.maintenanceModeEnabled || false,
|
||||||
|
maintenanceModeType: resource.maintenanceModeType || "automatic",
|
||||||
|
maintenanceTitle:
|
||||||
|
resource.maintenanceTitle || "We'll be back soon!",
|
||||||
|
maintenanceMessage:
|
||||||
|
resource.maintenanceMessage ||
|
||||||
|
"We are currently performing scheduled maintenance. Please check back soon.",
|
||||||
|
maintenanceEstimatedTime: resource.maintenanceEstimatedTime || ""
|
||||||
|
},
|
||||||
|
mode: "onChange"
|
||||||
|
});
|
||||||
|
|
||||||
|
const isMaintenanceEnabled = maintenanceForm.watch(
|
||||||
|
"maintenanceModeEnabled"
|
||||||
|
);
|
||||||
|
const maintenanceModeType = maintenanceForm.watch("maintenanceModeType");
|
||||||
|
|
||||||
|
const [, maintenanceFormAction, maintenanceSaveLoading] = useActionState(
|
||||||
|
onMaintenanceSubmit,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
async function onMaintenanceSubmit() {
|
||||||
|
const isValid = await maintenanceForm.trigger();
|
||||||
|
if (!isValid) return;
|
||||||
|
|
||||||
|
const data = maintenanceForm.getValues();
|
||||||
|
|
||||||
|
const res = await api
|
||||||
|
.post<AxiosResponse<UpdateResourceResponse>>(
|
||||||
|
`resource/${resource?.resourceId}`,
|
||||||
|
{
|
||||||
|
maintenanceModeEnabled: data.maintenanceModeEnabled,
|
||||||
|
maintenanceModeType: data.maintenanceModeType,
|
||||||
|
maintenanceTitle: data.maintenanceTitle || null,
|
||||||
|
maintenanceMessage: data.maintenanceMessage || null,
|
||||||
|
maintenanceEstimatedTime:
|
||||||
|
data.maintenanceEstimatedTime || null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch((e) => {
|
||||||
|
toast({
|
||||||
|
variant: "destructive",
|
||||||
|
title: t("resourceErrorUpdate"),
|
||||||
|
description: formatAxiosError(
|
||||||
|
e,
|
||||||
|
t("resourceErrorUpdateDescription")
|
||||||
|
)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res && res.status === 200) {
|
||||||
|
updateResource({
|
||||||
|
maintenanceModeEnabled: data.maintenanceModeEnabled,
|
||||||
|
maintenanceModeType: data.maintenanceModeType,
|
||||||
|
maintenanceTitle: data.maintenanceTitle || null,
|
||||||
|
maintenanceMessage: data.maintenanceMessage || null,
|
||||||
|
maintenanceEstimatedTime: data.maintenanceEstimatedTime || null
|
||||||
|
});
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: t("resourceUpdated"),
|
||||||
|
description: t("resourceUpdatedDescription")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSecurityFeatureDisabled = () => {
|
||||||
|
const isEnterpriseNotLicensed = build === "enterprise" && !isUnlocked();
|
||||||
|
const isSaasNotSubscribed =
|
||||||
|
build === "saas" && !subscription?.isSubscribed();
|
||||||
|
return isEnterpriseNotLicensed || isSaasNotSubscribed;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsSection>
|
||||||
|
<SettingsSectionHeader>
|
||||||
|
<SettingsSectionTitle>
|
||||||
|
{t("maintenanceMode")}
|
||||||
|
</SettingsSectionTitle>
|
||||||
|
<SettingsSectionDescription>
|
||||||
|
{t("maintenanceModeDescription")}
|
||||||
|
</SettingsSectionDescription>
|
||||||
|
</SettingsSectionHeader>
|
||||||
|
|
||||||
|
<SettingsSectionBody>
|
||||||
|
<SettingsSectionForm>
|
||||||
|
<Form {...maintenanceForm}>
|
||||||
|
<form
|
||||||
|
action={maintenanceFormAction}
|
||||||
|
className="space-y-4"
|
||||||
|
id="maintenance-settings-form"
|
||||||
|
>
|
||||||
|
<PaidFeaturesAlert></PaidFeaturesAlert>
|
||||||
|
<FormField
|
||||||
|
control={maintenanceForm.control}
|
||||||
|
name="maintenanceModeEnabled"
|
||||||
|
render={({ field }) => {
|
||||||
|
const isDisabled =
|
||||||
|
isSecurityFeatureDisabled();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItem>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<FormControl>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger
|
||||||
|
asChild
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<SwitchInput
|
||||||
|
id="enable-maintenance"
|
||||||
|
checked={
|
||||||
|
field.value
|
||||||
|
}
|
||||||
|
label={t(
|
||||||
|
"enableMaintenanceMode"
|
||||||
|
)}
|
||||||
|
disabled={
|
||||||
|
isDisabled
|
||||||
|
}
|
||||||
|
onCheckedChange={(
|
||||||
|
val
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
!isDisabled
|
||||||
|
) {
|
||||||
|
maintenanceForm.setValue(
|
||||||
|
"maintenanceModeEnabled",
|
||||||
|
val
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isMaintenanceEnabled && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<FormField
|
||||||
|
control={maintenanceForm.control}
|
||||||
|
name="maintenanceModeType"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="space-y-3">
|
||||||
|
<FormLabel>
|
||||||
|
{t("maintenanceModeType")}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={
|
||||||
|
field.onChange
|
||||||
|
}
|
||||||
|
defaultValue={
|
||||||
|
field.value
|
||||||
|
}
|
||||||
|
disabled={isSecurityFeatureDisabled()}
|
||||||
|
className="flex flex-col space-y-1"
|
||||||
|
>
|
||||||
|
<FormItem className="flex items-start space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="automatic" />
|
||||||
|
</FormControl>
|
||||||
|
<div className="space-y-1 leading-none">
|
||||||
|
<FormLabel className="font-normal">
|
||||||
|
<strong>
|
||||||
|
{t(
|
||||||
|
"automatic"
|
||||||
|
)}
|
||||||
|
</strong>{" "}
|
||||||
|
(
|
||||||
|
{t(
|
||||||
|
"recommended"
|
||||||
|
)}
|
||||||
|
)
|
||||||
|
</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"automaticModeDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem className="flex items-start space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="forced" />
|
||||||
|
</FormControl>
|
||||||
|
<div className="space-y-1 leading-none">
|
||||||
|
<FormLabel className="font-normal">
|
||||||
|
<strong>
|
||||||
|
{t(
|
||||||
|
"forced"
|
||||||
|
)}
|
||||||
|
</strong>
|
||||||
|
</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"forcedModeDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{maintenanceModeType === "forced" && (
|
||||||
|
<Alert variant={"neutral"}>
|
||||||
|
<AlertCircle className="h-4 w-4" />
|
||||||
|
<AlertDescription>
|
||||||
|
{t("forcedeModeWarning")}
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={maintenanceForm.control}
|
||||||
|
name="maintenanceTitle"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t("pageTitle")}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
disabled={isSecurityFeatureDisabled()}
|
||||||
|
placeholder="We'll be back soon!"
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t("pageTitleDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={maintenanceForm.control}
|
||||||
|
name="maintenanceMessage"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"maintenancePageMessage"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea
|
||||||
|
{...field}
|
||||||
|
rows={4}
|
||||||
|
disabled={isSecurityFeatureDisabled()}
|
||||||
|
placeholder={t(
|
||||||
|
"maintenancePageMessagePlaceholder"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"maintenancePageMessageDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={maintenanceForm.control}
|
||||||
|
name="maintenanceEstimatedTime"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
"maintenancePageTimeTitle"
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
disabled={isSecurityFeatureDisabled()}
|
||||||
|
placeholder={t(
|
||||||
|
"maintenanceTime"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t(
|
||||||
|
"maintenanceEstimatedTimeDescription"
|
||||||
|
)}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</SettingsSectionForm>
|
||||||
|
</SettingsSectionBody>
|
||||||
|
|
||||||
|
<SettingsSectionFooter>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
loading={maintenanceSaveLoading}
|
||||||
|
disabled={maintenanceSaveLoading}
|
||||||
|
form="maintenance-settings-form"
|
||||||
|
>
|
||||||
|
{t("saveSettings")}
|
||||||
|
</Button>
|
||||||
|
</SettingsSectionFooter>
|
||||||
|
</SettingsSection>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function GeneralForm() {
|
export default function GeneralForm() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@@ -68,8 +425,6 @@ export default function GeneralForm() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const [editDomainOpen, setEditDomainOpen] = useState(false);
|
const [editDomainOpen, setEditDomainOpen] = useState(false);
|
||||||
const { isUnlocked } = useLicenseStatusContext();
|
|
||||||
const subscription = useSubscriptionStatusContext();
|
|
||||||
|
|
||||||
const { env } = useEnvContext();
|
const { env } = useEnvContext();
|
||||||
|
|
||||||
@@ -94,14 +449,6 @@ export default function GeneralForm() {
|
|||||||
baseDomain: string;
|
baseDomain: string;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
// Check if security features are disabled due to licensing/subscription
|
|
||||||
const isSecurityFeatureDisabled = () => {
|
|
||||||
const isEnterpriseNotLicensed = build === "enterprise" && !isUnlocked();
|
|
||||||
const isSaasNotSubscribed =
|
|
||||||
build === "saas" && !subscription?.isSubscribed();
|
|
||||||
return isEnterpriseNotLicensed || isSaasNotSubscribed;
|
|
||||||
};
|
|
||||||
|
|
||||||
const GeneralFormSchema = z
|
const GeneralFormSchema = z
|
||||||
.object({
|
.object({
|
||||||
enabled: z.boolean(),
|
enabled: z.boolean(),
|
||||||
@@ -109,12 +456,7 @@ export default function GeneralForm() {
|
|||||||
name: z.string().min(1).max(255),
|
name: z.string().min(1).max(255),
|
||||||
niceId: z.string().min(1).max(255).optional(),
|
niceId: z.string().min(1).max(255).optional(),
|
||||||
domainId: z.string().optional(),
|
domainId: z.string().optional(),
|
||||||
proxyPort: z.number().int().min(1).max(65535).optional(),
|
proxyPort: z.number().int().min(1).max(65535).optional()
|
||||||
maintenanceModeEnabled: z.boolean().optional(),
|
|
||||||
maintenanceModeType: z.enum(["forced", "automatic"]).optional(),
|
|
||||||
maintenanceTitle: z.string().max(255).optional(),
|
|
||||||
maintenanceMessage: z.string().max(2000).optional(),
|
|
||||||
maintenanceEstimatedTime: z.string().max(100).optional()
|
|
||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
@@ -143,22 +485,11 @@ export default function GeneralForm() {
|
|||||||
niceId: resource.niceId,
|
niceId: resource.niceId,
|
||||||
subdomain: resource.subdomain ? resource.subdomain : undefined,
|
subdomain: resource.subdomain ? resource.subdomain : undefined,
|
||||||
domainId: resource.domainId || undefined,
|
domainId: resource.domainId || undefined,
|
||||||
proxyPort: resource.proxyPort || undefined,
|
proxyPort: resource.proxyPort || undefined
|
||||||
maintenanceModeEnabled: resource.maintenanceModeEnabled || false,
|
|
||||||
maintenanceModeType: resource.maintenanceModeType || "automatic",
|
|
||||||
maintenanceTitle:
|
|
||||||
resource.maintenanceTitle || "We'll be back soon!",
|
|
||||||
maintenanceMessage:
|
|
||||||
resource.maintenanceMessage ||
|
|
||||||
"We are currently performing scheduled maintenance. Please check back soon.",
|
|
||||||
maintenanceEstimatedTime: resource.maintenanceEstimatedTime || ""
|
|
||||||
},
|
},
|
||||||
mode: "onChange"
|
mode: "onChange"
|
||||||
});
|
});
|
||||||
|
|
||||||
const isMaintenanceEnabled = form.watch("maintenanceModeEnabled");
|
|
||||||
const maintenanceModeType = form.watch("maintenanceModeType");
|
|
||||||
|
|
||||||
const [, formAction, saveLoading] = useActionState(onSubmit, null);
|
const [, formAction, saveLoading] = useActionState(onSubmit, null);
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
@@ -178,13 +509,7 @@ export default function GeneralForm() {
|
|||||||
? toASCII(data.subdomain)
|
? toASCII(data.subdomain)
|
||||||
: undefined,
|
: undefined,
|
||||||
domainId: data.domainId,
|
domainId: data.domainId,
|
||||||
proxyPort: data.proxyPort,
|
proxyPort: data.proxyPort
|
||||||
maintenanceModeEnabled: data.maintenanceModeEnabled,
|
|
||||||
maintenanceModeType: data.maintenanceModeType,
|
|
||||||
maintenanceTitle: data.maintenanceTitle || null,
|
|
||||||
maintenanceMessage: data.maintenanceMessage || null,
|
|
||||||
maintenanceEstimatedTime:
|
|
||||||
data.maintenanceEstimatedTime || null
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@@ -208,12 +533,7 @@ export default function GeneralForm() {
|
|||||||
subdomain: data.subdomain,
|
subdomain: data.subdomain,
|
||||||
fullDomain: updated.fullDomain,
|
fullDomain: updated.fullDomain,
|
||||||
proxyPort: data.proxyPort,
|
proxyPort: data.proxyPort,
|
||||||
domainId: data.domainId,
|
domainId: data.domainId
|
||||||
maintenanceModeEnabled: data.maintenanceModeEnabled,
|
|
||||||
maintenanceModeType: data.maintenanceModeType,
|
|
||||||
maintenanceTitle: data.maintenanceTitle || null,
|
|
||||||
maintenanceMessage: data.maintenanceMessage || null,
|
|
||||||
maintenanceEstimatedTime: data.maintenanceEstimatedTime || null
|
|
||||||
});
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@@ -337,8 +657,11 @@ export default function GeneralForm() {
|
|||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
value={
|
value={
|
||||||
field.value !== undefined
|
field.value !==
|
||||||
? String(field.value)
|
undefined
|
||||||
|
? String(
|
||||||
|
field.value
|
||||||
|
)
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -388,239 +711,6 @@ export default function GeneralForm() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<PaidFeaturesAlert></PaidFeaturesAlert>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="maintenanceModeEnabled"
|
|
||||||
render={({ field }) => {
|
|
||||||
const isDisabled =
|
|
||||||
isSecurityFeatureDisabled();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormItem>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<FormControl>
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger
|
|
||||||
asChild
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<SwitchInput
|
|
||||||
id="enable-maintenance"
|
|
||||||
checked={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
label={t(
|
|
||||||
"enableMaintenanceMode"
|
|
||||||
)}
|
|
||||||
disabled={
|
|
||||||
isDisabled
|
|
||||||
}
|
|
||||||
onCheckedChange={(
|
|
||||||
val
|
|
||||||
) => {
|
|
||||||
if (
|
|
||||||
!isDisabled
|
|
||||||
) {
|
|
||||||
form.setValue(
|
|
||||||
"maintenanceModeEnabled",
|
|
||||||
val
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</FormControl>
|
|
||||||
</div>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"showMaintenancePage"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{isMaintenanceEnabled && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="maintenanceModeType"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="space-y-3">
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"maintenanceModeType"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<RadioGroup
|
|
||||||
onValueChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
defaultValue={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
disabled={isSecurityFeatureDisabled()}
|
|
||||||
className="flex flex-col space-y-1"
|
|
||||||
>
|
|
||||||
<FormItem className="flex items-start space-x-3 space-y-0">
|
|
||||||
<FormControl>
|
|
||||||
<RadioGroupItem value="automatic" />
|
|
||||||
</FormControl>
|
|
||||||
<div className="space-y-1 leading-none">
|
|
||||||
<FormLabel className="font-normal">
|
|
||||||
<strong>
|
|
||||||
{t(
|
|
||||||
"automatic"
|
|
||||||
)}
|
|
||||||
</strong>{" "}
|
|
||||||
(
|
|
||||||
{t(
|
|
||||||
"recommended"
|
|
||||||
)}
|
|
||||||
)
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"automaticModeDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem className="flex items-start space-x-3 space-y-0">
|
|
||||||
<FormControl>
|
|
||||||
<RadioGroupItem value="forced" />
|
|
||||||
</FormControl>
|
|
||||||
<div className="space-y-1 leading-none">
|
|
||||||
<FormLabel className="font-normal">
|
|
||||||
<strong>
|
|
||||||
{t(
|
|
||||||
"forced"
|
|
||||||
)}
|
|
||||||
</strong>
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"forcedModeDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
|
||||||
</FormItem>
|
|
||||||
</RadioGroup>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{maintenanceModeType ===
|
|
||||||
"forced" && (
|
|
||||||
<Alert>
|
|
||||||
<AlertCircle className="h-4 w-4" />
|
|
||||||
<AlertDescription>
|
|
||||||
<strong>
|
|
||||||
{t("warning:")}
|
|
||||||
</strong>{" "}
|
|
||||||
{t(
|
|
||||||
"forcedeModeWarning"
|
|
||||||
)}
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="maintenanceTitle"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("pageTitle")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
disabled={isSecurityFeatureDisabled()}
|
|
||||||
placeholder="We'll be back soon!"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"pageTitleDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="maintenanceMessage"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"maintenancePageMessage"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Textarea
|
|
||||||
{...field}
|
|
||||||
rows={4}
|
|
||||||
disabled={isSecurityFeatureDisabled()}
|
|
||||||
placeholder={t(
|
|
||||||
"maintenancePageMessagePlaceholder"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"maintenancePageMessageDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="maintenanceEstimatedTime"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"maintenancePageTimeTitle"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
disabled={isSecurityFeatureDisabled()}
|
|
||||||
placeholder={t(
|
|
||||||
"maintenanceTime"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"maintenanceEstimatedTimeDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</SettingsSectionForm>
|
</SettingsSectionForm>
|
||||||
@@ -637,6 +727,13 @@ export default function GeneralForm() {
|
|||||||
</Button>
|
</Button>
|
||||||
</SettingsSectionFooter>
|
</SettingsSectionFooter>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
|
|
||||||
|
{build !== "oss" && (
|
||||||
|
<MaintenanceSectionForm
|
||||||
|
resource={resource}
|
||||||
|
updateResource={updateResource}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</SettingsContainer>
|
</SettingsContainer>
|
||||||
|
|
||||||
<Credenza
|
<Credenza
|
||||||
|
|||||||
Reference in New Issue
Block a user