small branding fixes and adjustments

This commit is contained in:
miloschwartz
2025-12-17 15:02:26 -05:00
parent f892acbc4c
commit 4aef7ca8d5
4 changed files with 44 additions and 123 deletions

View File

@@ -1807,11 +1807,12 @@
"idpAzureDescription": "Microsoft Azure OAuth2/OIDC provider",
"subnet": "Subnet",
"subnetDescription": "The subnet for this organization's network configuration.",
"authPage": "Auth Page",
"authPageDescription": "Configure the auth page for the organization",
"customDomain": "Custom Domain",
"authPage": "Authentication Pages",
"authPageDescription": "Set a custom domain for the organization's authentication pages",
"authPageDomain": "Auth Page Domain",
"authPageBranding": "Branding",
"authPageBrandingDescription": "Configure the branding for the auth page for your organization",
"authPageBranding": "Custom Branding",
"authPageBrandingDescription": "Configure the branding that appears on authentication pages for this organization",
"authPageBrandingUpdated": "Auth page Branding updated successfully",
"authPageBrandingRemoved": "Auth page Branding removed successfully",
"authPageBrandingRemoveTitle": "Remove Auth Page Branding",
@@ -1838,7 +1839,7 @@
"setAuthPageDomain": "Set Auth Page Domain",
"failedToFetchCertificate": "Failed to fetch certificate",
"failedToRestartCertificate": "Failed to restart certificate",
"addDomainToEnableCustomAuthPages": "Add a domain to enable custom authentication pages for the organization",
"addDomainToEnableCustomAuthPages": "Users will be able to access the organization's login page and complete resource authentication using this domain.",
"selectDomainForOrgAuthPage": "Select a domain for the organization's authentication page",
"domainPickerProvidedDomain": "Provided Domain",
"domainPickerFreeProvidedDomain": "Free Provided Domain",
@@ -2303,5 +2304,9 @@
"allPortsAllowed": "All Ports Allowed",
"allPortsBlocked": "All Ports Blocked",
"tcpPortsDescription": "Specify which TCP ports are allowed for this resource. Use '*' for all ports, leave empty to block all, or enter a comma-separated list of ports and ranges (e.g., 80,443,8000-9000).",
"udpPortsDescription": "Specify which UDP ports are allowed for this resource. Use '*' for all ports, leave empty to block all, or enter a comma-separated list of ports and ranges (e.g., 53,123,500-600)."
"udpPortsDescription": "Specify which UDP ports are allowed for this resource. Use '*' for all ports, leave empty to block all, or enter a comma-separated list of ports and ranges (e.g., 53,123,500-600).",
"organizationLoginPageTitle": "Organization Login Page",
"organizationLoginPageDescription": "Customize the login page for this organization",
"resourceLoginPageTitle": "Resource Login Page",
"resourceLoginPageDescription": "Customize the login page for individual resources"
}

View File

@@ -1,19 +1,16 @@
import AuthPageBrandingForm from "@app/components/AuthPageBrandingForm";
import AuthPageSettings from "@app/components/private/AuthPageSettings";
import { SettingsContainer } from "@app/components/Settings";
import { internal, priv } from "@app/lib/api";
import { internal } from "@app/lib/api";
import { authCookieHeader } from "@app/lib/api/cookies";
import { getCachedSubscription } from "@app/lib/api/getCachedSubscription";
import { pullEnv } from "@app/lib/pullEnv";
import { build } from "@server/build";
import { TierId } from "@server/lib/billing/tiers";
import type { GetOrgTierResponse } from "@server/routers/billing/types";
import {
GetLoginPageBrandingResponse,
GetLoginPageResponse
} from "@server/routers/loginPage/types";
import { AxiosResponse } from "axios";
import { redirect } from "next/navigation";
export interface AuthPageProps {
params: Promise<{ orgId: string }>;
@@ -21,20 +18,11 @@ export interface AuthPageProps {
export default async function AuthPage(props: AuthPageProps) {
const orgId = (await props.params).orgId;
const env = pullEnv();
let subscriptionStatus: GetOrgTierResponse | null = null;
try {
const subRes = await getCachedSubscription(orgId);
subscriptionStatus = subRes.data.data;
} catch {}
const subscribed =
build === "enterprise"
? true
: subscriptionStatus?.tier === TierId.STANDARD;
if (!subscribed) {
redirect(env.app.dashboardUrl);
}
let loginPage: GetLoginPageResponse | null = null;
try {

View File

@@ -25,25 +25,16 @@ import { useTranslations } from "next-intl";
import type { GetLoginPageBrandingResponse } from "@server/routers/loginPage/types";
import { Input } from "./ui/input";
import { Trash2, XIcon } from "lucide-react";
import { ExternalLink, InfoIcon, XIcon } from "lucide-react";
import { Button } from "./ui/button";
import { Separator } from "./ui/separator";
import { createApiClient, formatAxiosError } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext";
import { useRouter } from "next/navigation";
import { toast } from "@app/hooks/useToast";
import {
Credenza,
CredenzaBody,
CredenzaClose,
CredenzaContent,
CredenzaFooter,
CredenzaHeader,
CredenzaTitle
} from "./Credenza";
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { build } from "@server/build";
import { PaidFeaturesAlert } from "./PaidFeaturesAlert";
import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
export type AuthPageCustomizationProps = {
orgId: string;
@@ -99,7 +90,7 @@ export default function AuthPageBrandingForm({
deleteBranding,
null
);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [setIsDeleteModalOpen] = useState(false);
const t = useTranslations();
@@ -166,7 +157,6 @@ export default function AuthPageBrandingForm({
if (updateRes.status === 200) {
router.refresh();
form.reset();
setIsDeleteModalOpen(false);
toast({
variant: "default",
@@ -198,15 +188,15 @@ export default function AuthPageBrandingForm({
</SettingsSectionDescription>
</SettingsSectionHeader>
<PaidFeaturesAlert />
<SettingsSectionBody>
<SettingsSectionForm>
<PaidFeaturesAlert />
<Form {...form}>
<form
action={updateFormAction}
id="auth-page-branding-form"
className="flex flex-col gap-8 items-stretch"
className="flex flex-col space-y-4 items-stretch"
>
<FormField
control={form.control}
@@ -301,7 +291,18 @@ export default function AuthPageBrandingForm({
{build === "saas" && (
<>
<Separator />
<div className="mt-3 mb-6">
<SettingsSectionTitle>
{t(
"organizationLoginPageTitle"
)}
</SettingsSectionTitle>
<SettingsSectionDescription>
{t(
"organizationLoginPageDescription"
)}
</SettingsSectionDescription>
</div>
<div className="flex flex-col gap-5">
<FormField
@@ -318,15 +319,6 @@ export default function AuthPageBrandingForm({
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
{t(
"brandingOrgDescription",
{
orgName:
"{{orgName}}"
}
)}
</FormDescription>
<FormMessage />
</FormItem>
)}
@@ -345,15 +337,6 @@ export default function AuthPageBrandingForm({
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
{t(
"brandingOrgDescription",
{
orgName:
"{{orgName}}"
}
)}
</FormDescription>
<FormMessage />
</FormItem>
)}
@@ -362,7 +345,14 @@ export default function AuthPageBrandingForm({
</>
)}
<Separator />
<div className="mt-3 mb-6">
<SettingsSectionTitle>
{t("resourceLoginPageTitle")}
</SettingsSectionTitle>
<SettingsSectionDescription>
{t("resourceLoginPageDescription")}
</SettingsSectionDescription>
</div>
<div className="flex flex-col gap-5">
<FormField
@@ -377,15 +367,6 @@ export default function AuthPageBrandingForm({
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
{t(
"brandingResourceDescription",
{
resourceName:
"{{resourceName}}"
}
)}
</FormDescription>
<FormMessage />
</FormItem>
)}
@@ -403,15 +384,6 @@ export default function AuthPageBrandingForm({
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>
{t(
"brandingResourceDescription",
{
resourceName:
"{{resourceName}}"
}
)}
</FormDescription>
<FormMessage />
</FormItem>
)}
@@ -422,44 +394,6 @@ export default function AuthPageBrandingForm({
</SettingsSectionForm>
</SettingsSectionBody>
<Credenza
open={isDeleteModalOpen}
onOpenChange={setIsDeleteModalOpen}
>
<CredenzaContent>
<CredenzaHeader>
<CredenzaTitle>
{t("authPageBrandingRemoveTitle")}
</CredenzaTitle>
</CredenzaHeader>
<CredenzaBody className="mb-0 space-y-0 flex flex-col gap-1">
<p>{t("authPageBrandingQuestionRemove")}</p>
<div className="font-bold text-destructive">
{t("cannotbeUndone")}
</div>
<form
action={deleteFormAction}
id="confirm-delete-branding-form"
className="sr-only"
></form>
</CredenzaBody>
<CredenzaFooter>
<CredenzaClose asChild>
<Button variant="outline">{t("close")}</Button>
</CredenzaClose>
<Button
variant={"destructive"}
type="submit"
form="confirm-delete-branding-form"
loading={isDeletingBranding}
disabled={isDeletingBranding || !isPaidUser}
>
{t("authPageBrandingDeleteConfirm")}
</Button>
</CredenzaFooter>
</CredenzaContent>
</Credenza>
<div className="flex justify-end gap-2 mt-6 items-center">
{branding && (
<Button
@@ -472,12 +406,11 @@ export default function AuthPageBrandingForm({
!isPaidUser
}
onClick={() => {
setIsDeleteModalOpen(true);
deleteFormAction();
}}
className="gap-1"
>
{t("removeAuthPageBranding")}
<Trash2 size="14" />
</Button>
)}
<Button

View File

@@ -45,6 +45,7 @@ import { InfoPopup } from "@app/components/ui/info-popup";
import { Alert, AlertDescription } from "@app/components/ui/alert";
import { build } from "@server/build";
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { PaidFeaturesAlert } from "../PaidFeaturesAlert";
// Auth page form schema
const AuthPageFormSchema = z.object({
@@ -275,22 +276,16 @@ function AuthPageSettings({
<>
<SettingsSection>
<SettingsSectionHeader>
<SettingsSectionTitle>{t("authPage")}</SettingsSectionTitle>
<SettingsSectionTitle>{t("customDomain")}</SettingsSectionTitle>
<SettingsSectionDescription>
{t("authPageDescription")}
</SettingsSectionDescription>
</SettingsSectionHeader>
<SettingsSectionBody>
{!hasSaasSubscription ? (
<Alert variant="info" className="mb-6">
<AlertDescription>
{t("orgAuthPageDisabled")}{" "}
{t("subscriptionRequiredToUse")}
</AlertDescription>
</Alert>
) : null}
<SettingsSectionForm>
<PaidFeaturesAlert />
<Form {...form}>
<form
action={formAction}