mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-04 09:46:40 +00:00
add tooltip
This commit is contained in:
@@ -2386,5 +2386,7 @@
|
|||||||
"maintenanceTime": "e.g., 2 hours, Nov 1 at 5:00 PM",
|
"maintenanceTime": "e.g., 2 hours, Nov 1 at 5:00 PM",
|
||||||
"maintenanceEstimatedTimeDescription": "When you expect maintenance to be completed",
|
"maintenanceEstimatedTimeDescription": "When you expect maintenance to be completed",
|
||||||
"editDomain": "Edit Domain",
|
"editDomain": "Edit Domain",
|
||||||
"editDomainDescription": "Select a domain for your resource"
|
"editDomainDescription": "Select a domain for your resource",
|
||||||
|
"maintenanceModeDisabledTooltip": "This feature requires a valid license to enable."
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import {
|
|||||||
CredenzaTitle
|
CredenzaTitle
|
||||||
} from "@app/components/Credenza";
|
} from "@app/components/Credenza";
|
||||||
import DomainPicker from "@app/components/DomainPicker";
|
import DomainPicker from "@app/components/DomainPicker";
|
||||||
import { AlertCircle, Globe } from "lucide-react";
|
import { AlertCircle, Globe, Info } from "lucide-react";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { finalizeSubdomainSanitize } from "@app/lib/subdomain-utils";
|
import { finalizeSubdomainSanitize } from "@app/lib/subdomain-utils";
|
||||||
import { DomainRow } from "../../../../../../components/DomainsTable";
|
import { DomainRow } from "../../../../../../components/DomainsTable";
|
||||||
@@ -61,6 +61,7 @@ import { useSubscriptionStatusContext } from "@app/hooks/useSubscriptionStatusCo
|
|||||||
import { useUserContext } from "@app/hooks/useUserContext";
|
import { useUserContext } from "@app/hooks/useUserContext";
|
||||||
import { Alert, AlertDescription } from "@app/components/ui/alert";
|
import { Alert, AlertDescription } from "@app/components/ui/alert";
|
||||||
import { RadioGroup, RadioGroupItem } from "@app/components/ui/radio-group";
|
import { RadioGroup, RadioGroupItem } from "@app/components/ui/radio-group";
|
||||||
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@app/components/ui/tooltip";
|
||||||
|
|
||||||
export default function GeneralForm() {
|
export default function GeneralForm() {
|
||||||
const [formKey, setFormKey] = useState(0);
|
const [formKey, setFormKey] = useState(0);
|
||||||
@@ -70,8 +71,9 @@ 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 { licenseStatus } = useLicenseStatusContext();
|
|
||||||
const subscriptionStatus = useSubscriptionStatusContext();
|
const subscriptionStatus = useSubscriptionStatusContext();
|
||||||
|
const { licenseStatus, isUnlocked } = useLicenseStatusContext();
|
||||||
|
const subscription = useSubscriptionStatusContext();
|
||||||
const { user } = useUserContext();
|
const { user } = useUserContext();
|
||||||
|
|
||||||
const { env } = useEnvContext();
|
const { env } = useEnvContext();
|
||||||
@@ -99,6 +101,14 @@ 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(),
|
||||||
@@ -360,19 +370,19 @@ export default function GeneralForm() {
|
|||||||
|
|
||||||
{!resource.http && (
|
{!resource.http && (
|
||||||
<>
|
<>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="proxyPort"
|
name="proxyPort"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
{t(
|
{t(
|
||||||
"resourcePortNumber"
|
"resourcePortNumber"
|
||||||
)}
|
)}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
value={
|
value={
|
||||||
field.value ??
|
field.value ??
|
||||||
""
|
""
|
||||||
@@ -380,7 +390,7 @@ export default function GeneralForm() {
|
|||||||
onChange={(
|
onChange={(
|
||||||
e
|
e
|
||||||
) =>
|
) =>
|
||||||
field.onChange(
|
field.onChange(
|
||||||
e
|
e
|
||||||
.target
|
.target
|
||||||
.value
|
.value
|
||||||
@@ -389,20 +399,20 @@ export default function GeneralForm() {
|
|||||||
.target
|
.target
|
||||||
.value
|
.value
|
||||||
)
|
)
|
||||||
: undefined
|
: undefined
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
{t(
|
{t(
|
||||||
"resourcePortNumberDescription"
|
"resourcePortNumberDescription"
|
||||||
)}
|
)}
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* {build == "oss" && (
|
{/* {build == "oss" && (
|
||||||
<FormField
|
<FormField
|
||||||
@@ -445,9 +455,9 @@ export default function GeneralForm() {
|
|||||||
{resource.http && (
|
{resource.http && (
|
||||||
<>
|
<>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>
|
<Label>
|
||||||
{t("resourceDomain")}
|
{t("resourceDomain")}
|
||||||
</Label>
|
</Label>
|
||||||
<div className="border p-2 rounded-md flex items-center justify-between">
|
<div className="border p-2 rounded-md flex items-center justify-between">
|
||||||
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
||||||
<Globe size="14" />
|
<Globe size="14" />
|
||||||
@@ -458,15 +468,15 @@ export default function GeneralForm() {
|
|||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setEditDomainOpen(
|
setEditDomainOpen(
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t(
|
{t(
|
||||||
"resourceEditDomain"
|
"resourceEditDomain"
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@@ -511,29 +521,55 @@ export default function GeneralForm() {
|
|||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="maintenanceModeEnabled"
|
name="maintenanceModeEnabled"
|
||||||
render={({ field }) => (
|
render={({ field }) => {
|
||||||
<FormItem>
|
const isDisabled =
|
||||||
<div className="flex items-center space-x-2">
|
isSecurityFeatureDisabled();
|
||||||
<FormControl>
|
|
||||||
<SwitchInput
|
return (
|
||||||
id="enable-maintenance"
|
|
||||||
checked={field.value}
|
<FormItem>
|
||||||
label={t("enableMaintenanceMode")}
|
<div className="flex items-center space-x-2">
|
||||||
onCheckedChange={(val) =>
|
<FormControl>
|
||||||
form.setValue(
|
<TooltipProvider>
|
||||||
"maintenanceModeEnabled",
|
<Tooltip>
|
||||||
val
|
<TooltipTrigger asChild>
|
||||||
)
|
<div className="flex items-center gap-2">
|
||||||
}
|
<span
|
||||||
/>
|
className={isDisabled ? "pointer-events-auto" : ""}
|
||||||
</FormControl>
|
>
|
||||||
</div>
|
<SwitchInput
|
||||||
<FormDescription>
|
id="enable-maintenance"
|
||||||
{t("showMaintenancePage")}
|
checked={field.value}
|
||||||
</FormDescription>
|
label={t("enableMaintenanceMode")}
|
||||||
<FormMessage />
|
disabled={isDisabled}
|
||||||
</FormItem>
|
onCheckedChange={(val) => {
|
||||||
)}
|
if (!isDisabled) {
|
||||||
|
form.setValue("maintenanceModeEnabled", val);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
|
||||||
|
{isDisabled && (
|
||||||
|
<TooltipContent className="max-w-xs">
|
||||||
|
<p>{t("maintenanceModeDisabledTooltip")}</p>
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
|
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
<FormDescription>
|
||||||
|
{t("showMaintenancePage")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isMaintenanceEnabled && (
|
{isMaintenanceEnabled && (
|
||||||
@@ -666,9 +702,9 @@ export default function GeneralForm() {
|
|||||||
<SettingsSectionFooter>
|
<SettingsSectionFooter>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log(form.getValues());
|
console.log(form.getValues());
|
||||||
}}
|
}}
|
||||||
loading={saveLoading}
|
loading={saveLoading}
|
||||||
disabled={saveLoading}
|
disabled={saveLoading}
|
||||||
form="general-settings-form"
|
form="general-settings-form"
|
||||||
|
|||||||
Reference in New Issue
Block a user