mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-17 04:47:11 +00:00
Merge pull request #3277 from fosrl/dev
Fix middleware and suppoter footer
This commit is contained in:
@@ -1294,16 +1294,14 @@ export async function getTraefikConfig(
|
||||
}
|
||||
};
|
||||
|
||||
// Assets router at higher priority so /_next files load without rewrite
|
||||
// Assets router at higher priority so /_next files load without rewrite.
|
||||
// Do NOT apply the path-rewrite middleware here — static assets must
|
||||
// keep their original path; only the host headers are needed.
|
||||
config_output.http.routers![
|
||||
`bg-r${bgResource.resourceId}-assets-router`
|
||||
] = {
|
||||
entryPoints: [entrypoint],
|
||||
middlewares: [
|
||||
...routerMiddlewares,
|
||||
uiRewriteMiddlewareName,
|
||||
uiHeadersMiddlewareName
|
||||
],
|
||||
middlewares: [...routerMiddlewares, uiHeadersMiddlewareName],
|
||||
service: bgUiServiceName,
|
||||
rule: `${hostRule} && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`) || Path(\`/favicon.ico\`))`,
|
||||
priority: 101,
|
||||
|
||||
@@ -3,7 +3,6 @@ import HttpCode from "@server/types/HttpCode";
|
||||
import createHttpError from "http-errors";
|
||||
import logger from "@server/logger";
|
||||
import { response as sendResponse } from "@server/lib/response";
|
||||
import config from "@server/lib/config";
|
||||
import { build } from "@server/build";
|
||||
import { APP_VERSION } from "@server/lib/consts";
|
||||
import license from "#dynamic/license/license";
|
||||
@@ -22,9 +21,6 @@ export async function getServerInfo(
|
||||
next: NextFunction
|
||||
): Promise<any> {
|
||||
try {
|
||||
const supporterData = config.getSupporterData();
|
||||
const supporterStatusValid = supporterData?.valid || false;
|
||||
|
||||
let enterpriseLicenseValid = false;
|
||||
let enterpriseLicenseType: string | null = null;
|
||||
|
||||
@@ -41,7 +37,7 @@ export async function getServerInfo(
|
||||
return sendResponse<GetServerInfoResponse>(res, {
|
||||
data: {
|
||||
version: APP_VERSION,
|
||||
supporterStatusValid,
|
||||
supporterStatusValid: true,
|
||||
build,
|
||||
enterpriseLicenseValid,
|
||||
enterpriseLicenseType
|
||||
|
||||
@@ -42,7 +42,14 @@ import {
|
||||
SettingsSectionFooter
|
||||
} from "@app/components/Settings";
|
||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||
import { ArrowRight, Check, ExternalLink, Heart, InfoIcon, TicketCheck } from "lucide-react";
|
||||
import {
|
||||
ArrowRight,
|
||||
Check,
|
||||
ExternalLink,
|
||||
Heart,
|
||||
InfoIcon,
|
||||
TicketCheck
|
||||
} from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import DismissableBanner from "@app/components/DismissableBanner";
|
||||
import CopyTextBox from "@app/components/CopyTextBox";
|
||||
@@ -50,7 +57,7 @@ import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog";
|
||||
import { SitePriceCalculator } from "@app/components/SitePriceCalculator";
|
||||
import { Checkbox } from "@app/components/ui/checkbox";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
||||
import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||
// import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const ENTERPRISE_DOCS_URL =
|
||||
@@ -82,7 +89,7 @@ export default function LicensePage() {
|
||||
const [isActivatingLicense, setIsActivatingLicense] = useState(false);
|
||||
const [isDeletingLicense, setIsDeletingLicense] = useState(false);
|
||||
const [isRecheckingLicense, setIsRecheckingLicense] = useState(false);
|
||||
const { supporterStatus } = useSupporterStatusContext();
|
||||
// const { supporterStatus } = useSupporterStatusContext();
|
||||
|
||||
const t = useTranslations();
|
||||
|
||||
@@ -347,9 +354,7 @@ export default function LicensePage() {
|
||||
storageKey="license-banner-dismissed"
|
||||
version={1}
|
||||
title={t("licenseBannerTitle")}
|
||||
titleIcon={
|
||||
<TicketCheck className="w-5 h-5 text-primary" />
|
||||
}
|
||||
titleIcon={<TicketCheck className="w-5 h-5 text-primary" />}
|
||||
description={t("licenseBannerDescription")}
|
||||
>
|
||||
<Link
|
||||
|
||||
@@ -68,15 +68,15 @@ export default async function RootLayout({
|
||||
const env = pullEnv();
|
||||
const locale = await getLocale();
|
||||
|
||||
const supporterData = {
|
||||
visible: true
|
||||
} as any;
|
||||
// const supporterData = {
|
||||
// visible: true
|
||||
// } as any;
|
||||
|
||||
const res = await priv.get<AxiosResponse<IsSupporterKeyVisibleResponse>>(
|
||||
"supporter-key/visible"
|
||||
);
|
||||
supporterData.visible = res.data.data.visible;
|
||||
supporterData.tier = res.data.data.tier;
|
||||
// const res = await priv.get<AxiosResponse<IsSupporterKeyVisibleResponse>>(
|
||||
// "supporter-key/visible"
|
||||
// );
|
||||
// supporterData.visible = res.data.data.visible;
|
||||
// supporterData.tier = res.data.data.tier;
|
||||
|
||||
let licenseStatus: GetLicenseStatusResponse;
|
||||
if (build === "enterprise") {
|
||||
@@ -127,20 +127,20 @@ export default async function RootLayout({
|
||||
<LicenseStatusProvider
|
||||
licenseStatus={licenseStatus}
|
||||
>
|
||||
<SupportStatusProvider
|
||||
{/* <SupportStatusProvider
|
||||
supporterStatus={supporterData}
|
||||
>
|
||||
{/* Main content */}
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="flex-1 overflow-auto">
|
||||
<SplashImage>
|
||||
<LicenseViolation />
|
||||
{children}
|
||||
</SplashImage>
|
||||
> */}
|
||||
{/* Main content */}
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="flex-1 overflow-auto">
|
||||
<SplashImage>
|
||||
<LicenseViolation />
|
||||
</div>
|
||||
{children}
|
||||
</SplashImage>
|
||||
<LicenseViolation />
|
||||
</div>
|
||||
</SupportStatusProvider>
|
||||
</div>
|
||||
{/* </SupportStatusProvider> */}
|
||||
</LicenseStatusProvider>
|
||||
<Toaster />
|
||||
</TanstackQueryProvider>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||
// import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||
import { useLicenseStatusContext } from "@app/hooks/useLicenseStatusContext";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { build } from "@server/build";
|
||||
|
||||
export default function AuthPageFooterNotices() {
|
||||
const t = useTranslations();
|
||||
const { supporterStatus } = useSupporterStatusContext();
|
||||
// const { supporterStatus } = useSupporterStatusContext();
|
||||
const { isUnlocked, licenseStatus } = useLicenseStatusContext();
|
||||
|
||||
return (
|
||||
<>
|
||||
{supporterStatus?.visible && (
|
||||
{/* {supporterStatus?.visible && (
|
||||
<div className="text-center mt-2">
|
||||
<span className="text-sm text-muted-foreground opacity-50">
|
||||
{t("noSupportKey")}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
)} */}
|
||||
{build === "enterprise" && !isUnlocked() ? (
|
||||
<div className="text-center mt-2">
|
||||
<span className="text-sm font-medium text-muted-foreground">
|
||||
|
||||
@@ -9,33 +9,34 @@ export default function SupporterMessage({ tier }: { tier: string }) {
|
||||
const t = useTranslations();
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center space-x-2 whitespace-nowrap group">
|
||||
<span
|
||||
className="cursor-pointer"
|
||||
onClick={(e) => {
|
||||
// Get the bounding box of the element
|
||||
const rect = (
|
||||
e.target as HTMLElement
|
||||
).getBoundingClientRect();
|
||||
<></>
|
||||
// <div className="relative flex items-center space-x-2 whitespace-nowrap group">
|
||||
// <span
|
||||
// className="cursor-pointer"
|
||||
// onClick={(e) => {
|
||||
// // Get the bounding box of the element
|
||||
// const rect = (
|
||||
// e.target as HTMLElement
|
||||
// ).getBoundingClientRect();
|
||||
|
||||
// Trigger confetti centered on the word "Pangolin"
|
||||
confetti({
|
||||
particleCount: 100,
|
||||
spread: 70,
|
||||
origin: {
|
||||
x: (rect.left + rect.width / 2) / window.innerWidth,
|
||||
y: rect.top / window.innerHeight
|
||||
},
|
||||
colors: ["#FFA500", "#FF4500", "#FFD700"]
|
||||
});
|
||||
}}
|
||||
>
|
||||
Pangolin
|
||||
</span>
|
||||
<Star className="w-3 h-3" />
|
||||
<div className="absolute left-1/2 transform -translate-x-1/2 -top-10 hidden group-hover:block text-primary text-sm rounded-md border shadow-md px-4 py-2 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
{t("componentsSupporterMessage", { tier: tier })}
|
||||
</div>
|
||||
</div>
|
||||
// // Trigger confetti centered on the word "Pangolin"
|
||||
// confetti({
|
||||
// particleCount: 100,
|
||||
// spread: 70,
|
||||
// origin: {
|
||||
// x: (rect.left + rect.width / 2) / window.innerWidth,
|
||||
// y: rect.top / window.innerHeight
|
||||
// },
|
||||
// colors: ["#FFA500", "#FF4500", "#FFD700"]
|
||||
// });
|
||||
// }}
|
||||
// >
|
||||
// Pangolin
|
||||
// </span>
|
||||
// <Star className="w-3 h-3" />
|
||||
// <div className="absolute left-1/2 transform -translate-x-1/2 -top-10 hidden group-hover:block text-primary text-sm rounded-md border shadow-md px-4 py-2 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
// {t("componentsSupporterMessage", { tier: tier })}
|
||||
// </div>
|
||||
// </div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// THIS IS DEPRECATED AND IS NO LONGER SHOWED TO THE USER WITH THE DISCONTINUATION
|
||||
// OF THE SUPPORTER PROGRAM. IT MAY BE REMOVED IN A FUTURE UPDATE.
|
||||
|
||||
import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||
// import { useSupporterStatusContext } from "@app/hooks/useSupporterStatusContext";
|
||||
import { useState, useTransition } from "react";
|
||||
import {
|
||||
Tooltip,
|
||||
@@ -58,134 +58,134 @@ interface SupporterStatusProps {
|
||||
export default function SupporterStatus({
|
||||
isCollapsed = false
|
||||
}: SupporterStatusProps) {
|
||||
const { supporterStatus, updateSupporterStatus } =
|
||||
useSupporterStatusContext();
|
||||
const [supportOpen, setSupportOpen] = useState(false);
|
||||
const [keyOpen, setKeyOpen] = useState(false);
|
||||
const [purchaseOptionsOpen, setPurchaseOptionsOpen] = useState(false);
|
||||
// const { supporterStatus, updateSupporterStatus } =
|
||||
// useSupporterStatusContext();
|
||||
// const [supportOpen, setSupportOpen] = useState(false);
|
||||
// const [keyOpen, setKeyOpen] = useState(false);
|
||||
// const [purchaseOptionsOpen, setPurchaseOptionsOpen] = useState(false);
|
||||
|
||||
const { env } = useEnvContext();
|
||||
const api = createApiClient({ env });
|
||||
const t = useTranslations();
|
||||
// const { env } = useEnvContext();
|
||||
// const api = createApiClient({ env });
|
||||
// const t = useTranslations();
|
||||
|
||||
const formSchema = z.object({
|
||||
githubUsername: z.string().nonempty({
|
||||
error: "GitHub username is required"
|
||||
}),
|
||||
key: z.string().nonempty({
|
||||
error: "Supporter key is required"
|
||||
})
|
||||
});
|
||||
// const formSchema = z.object({
|
||||
// githubUsername: z.string().nonempty({
|
||||
// error: "GitHub username is required"
|
||||
// }),
|
||||
// key: z.string().nonempty({
|
||||
// error: "Supporter key is required"
|
||||
// })
|
||||
// });
|
||||
|
||||
const form = useForm({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
githubUsername: "",
|
||||
key: ""
|
||||
}
|
||||
});
|
||||
// const form = useForm({
|
||||
// resolver: zodResolver(formSchema),
|
||||
// defaultValues: {
|
||||
// githubUsername: "",
|
||||
// key: ""
|
||||
// }
|
||||
// });
|
||||
|
||||
async function hide() {
|
||||
await api.post("/supporter-key/hide");
|
||||
// async function hide() {
|
||||
// await api.post("/supporter-key/hide");
|
||||
|
||||
updateSupporterStatus({
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
// updateSupporterStatus({
|
||||
// visible: false
|
||||
// });
|
||||
// }
|
||||
|
||||
async function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
try {
|
||||
const res = await api.post<
|
||||
AxiosResponse<ValidateSupporterKeyResponse>
|
||||
>("/supporter-key/validate", {
|
||||
githubUsername: values.githubUsername,
|
||||
key: values.key
|
||||
});
|
||||
// async function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
// try {
|
||||
// const res = await api.post<
|
||||
// AxiosResponse<ValidateSupporterKeyResponse>
|
||||
// >("/supporter-key/validate", {
|
||||
// githubUsername: values.githubUsername,
|
||||
// key: values.key
|
||||
// });
|
||||
|
||||
const data = res.data.data;
|
||||
// const data = res.data.data;
|
||||
|
||||
if (!data || !data.valid) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t("supportKeyInvalid"),
|
||||
description: t("supportKeyInvalidDescription")
|
||||
});
|
||||
return;
|
||||
}
|
||||
// if (!data || !data.valid) {
|
||||
// toast({
|
||||
// variant: "destructive",
|
||||
// title: t("supportKeyInvalid"),
|
||||
// description: t("supportKeyInvalidDescription")
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Trigger the toast
|
||||
toast({
|
||||
variant: "default",
|
||||
title: t("supportKeyValid"),
|
||||
description: t("supportKeyValidDescription")
|
||||
});
|
||||
// // Trigger the toast
|
||||
// toast({
|
||||
// variant: "default",
|
||||
// title: t("supportKeyValid"),
|
||||
// description: t("supportKeyValidDescription")
|
||||
// });
|
||||
|
||||
// Fireworks-style confetti
|
||||
const duration = 5 * 1000; // 5 seconds
|
||||
const animationEnd = Date.now() + duration;
|
||||
const defaults = {
|
||||
startVelocity: 30,
|
||||
spread: 360,
|
||||
ticks: 60,
|
||||
zIndex: 0,
|
||||
colors: ["#FFA500", "#FF4500", "#FFD700"] // Orange hues
|
||||
};
|
||||
// // Fireworks-style confetti
|
||||
// const duration = 5 * 1000; // 5 seconds
|
||||
// const animationEnd = Date.now() + duration;
|
||||
// const defaults = {
|
||||
// startVelocity: 30,
|
||||
// spread: 360,
|
||||
// ticks: 60,
|
||||
// zIndex: 0,
|
||||
// colors: ["#FFA500", "#FF4500", "#FFD700"] // Orange hues
|
||||
// };
|
||||
|
||||
function randomInRange(min: number, max: number) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
// function randomInRange(min: number, max: number) {
|
||||
// return Math.random() * (max - min) + min;
|
||||
// }
|
||||
|
||||
const interval = setInterval(() => {
|
||||
const timeLeft = animationEnd - Date.now();
|
||||
// const interval = setInterval(() => {
|
||||
// const timeLeft = animationEnd - Date.now();
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
clearInterval(interval);
|
||||
return;
|
||||
}
|
||||
// if (timeLeft <= 0) {
|
||||
// clearInterval(interval);
|
||||
// return;
|
||||
// }
|
||||
|
||||
const particleCount = 50 * (timeLeft / duration);
|
||||
// const particleCount = 50 * (timeLeft / duration);
|
||||
|
||||
// Launch confetti from two random horizontal positions
|
||||
confetti({
|
||||
...defaults,
|
||||
particleCount,
|
||||
origin: {
|
||||
x: randomInRange(0.1, 0.3),
|
||||
y: Math.random() - 0.2
|
||||
}
|
||||
});
|
||||
confetti({
|
||||
...defaults,
|
||||
particleCount,
|
||||
origin: {
|
||||
x: randomInRange(0.7, 0.9),
|
||||
y: Math.random() - 0.2
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
// // Launch confetti from two random horizontal positions
|
||||
// confetti({
|
||||
// ...defaults,
|
||||
// particleCount,
|
||||
// origin: {
|
||||
// x: randomInRange(0.1, 0.3),
|
||||
// y: Math.random() - 0.2
|
||||
// }
|
||||
// });
|
||||
// confetti({
|
||||
// ...defaults,
|
||||
// particleCount,
|
||||
// origin: {
|
||||
// x: randomInRange(0.7, 0.9),
|
||||
// y: Math.random() - 0.2
|
||||
// }
|
||||
// });
|
||||
// }, 250);
|
||||
|
||||
setPurchaseOptionsOpen(false);
|
||||
setKeyOpen(false);
|
||||
// setPurchaseOptionsOpen(false);
|
||||
// setKeyOpen(false);
|
||||
|
||||
updateSupporterStatus({
|
||||
visible: false
|
||||
});
|
||||
} catch (error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t("error"),
|
||||
description: formatAxiosError(
|
||||
error,
|
||||
t("supportKeyErrorValidationDescription")
|
||||
)
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
// updateSupporterStatus({
|
||||
// visible: false
|
||||
// });
|
||||
// } catch (error) {
|
||||
// toast({
|
||||
// variant: "destructive",
|
||||
// title: t("error"),
|
||||
// description: formatAxiosError(
|
||||
// error,
|
||||
// t("supportKeyErrorValidationDescription")
|
||||
// )
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
return (
|
||||
<>
|
||||
<Credenza
|
||||
{/* <Credenza
|
||||
open={purchaseOptionsOpen}
|
||||
onOpenChange={(val) => {
|
||||
setPurchaseOptionsOpen(val);
|
||||
@@ -469,7 +469,7 @@ export default function SupporterStatus({
|
||||
{t("supportKeyBuy")}
|
||||
</Button>
|
||||
)
|
||||
) : null}
|
||||
) : null} */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user