chore: adds future opt-in banner for ADMINS only (#13315)
* chore: adds future opt-in banner for ADMINS only * Adds banner to shell * Update teams.e2e.ts * fix: e2e ab tests * Update ab-tests-redirect.e2e.ts * Discard changes to apps/web/playwright/ab-tests-redirect.e2e.ts * Discard changes to apps/web/playwright/app-store.e2e.ts * Discard changes to apps/web/playwright/event-types.e2e.ts * Discard changes to apps/web/playwright/payment.e2e.ts * Discard changes to apps/web/playwright/settings-admin.e2e.ts * Discard changes to apps/web/playwright/teams.e2e.ts --------- Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com>
This commit is contained in:
co-authored by
Peer Richelsen
Keith Williams
parent
fdaa6961f8
commit
a0a731b357
@@ -3,6 +3,8 @@ import type { NextMiddleware, NextRequest } from "next/server";
|
||||
import { NextResponse, URLPattern } from "next/server";
|
||||
import z from "zod";
|
||||
|
||||
import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME } from "@calcom/lib/constants";
|
||||
|
||||
const ROUTES: [URLPattern, boolean][] = [
|
||||
["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const,
|
||||
["/settings/admin/:path*", process.env.APP_ROUTER_SETTINGS_ADMIN_ENABLED === "1"] as const,
|
||||
@@ -25,9 +27,6 @@ const ROUTES: [URLPattern, boolean][] = [
|
||||
enabled,
|
||||
]);
|
||||
|
||||
const FUTURE_ROUTES_OVERRIDE_COOKIE_NAME = "x-calcom-future-routes-override";
|
||||
const FUTURE_ROUTES_ENABLED_COOKIE_NAME = "x-calcom-future-routes-enabled";
|
||||
|
||||
const bucketSchema = z.union([z.literal("legacy"), z.literal("future")]);
|
||||
|
||||
export const abTestMiddlewareFactory =
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { FUTURE_ROUTES_OVERRIDE_COOKIE_NAME as COOKIE_NAME } from "@calcom/lib/constants";
|
||||
import { defaultHandler, defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse): Promise<void> {
|
||||
const session = await getServerSession({ req, res });
|
||||
|
||||
if (!session || !session.user || !session.user.email) {
|
||||
res.status(401).json({ message: "Not authenticated" });
|
||||
return;
|
||||
}
|
||||
|
||||
let redirectUrl = "/";
|
||||
|
||||
// We take you back where you came from if possible
|
||||
if (typeof req.headers["referer"] === "string") redirectUrl = req.headers["referer"];
|
||||
|
||||
/* Only admins can opt-in to future routes for now */
|
||||
if (session.user.role !== "ADMIN") {
|
||||
res.redirect(redirectUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// If has the cookie, Opt-out of V2
|
||||
if (COOKIE_NAME in req.cookies && req.cookies[COOKIE_NAME] === "1") {
|
||||
res.setHeader("Set-Cookie", `${COOKIE_NAME}=0; Max-Age=0; Path=/`);
|
||||
} else {
|
||||
/* Opt-int to V2 */
|
||||
res.setHeader("Set-Cookie", `${COOKIE_NAME}=1; Path=/`);
|
||||
}
|
||||
|
||||
res.redirect(redirectUrl);
|
||||
}
|
||||
|
||||
export default defaultHandler({
|
||||
GET: Promise.resolve({ default: defaultResponder(handler) }),
|
||||
});
|
||||
@@ -29,6 +29,7 @@ import AdminPasswordBanner, {
|
||||
import CalendarCredentialBanner, {
|
||||
type CalendarCredentialBannerProps,
|
||||
} from "@calcom/features/users/components/CalendarCredentialBanner";
|
||||
import UserV2OptInBanner from "@calcom/features/users/components/UserV2OptInBanner";
|
||||
import VerifyEmailBanner, {
|
||||
type VerifyEmailBannerProps,
|
||||
} from "@calcom/features/users/components/VerifyEmailBanner";
|
||||
@@ -249,6 +250,7 @@ const Layout = (props: LayoutProps) => {
|
||||
<div className="flex min-h-screen flex-col">
|
||||
{banners && (
|
||||
<div className="sticky top-0 z-10 w-full divide-y divide-black">
|
||||
<UserV2OptInBanner />
|
||||
{Object.keys(banners).map((key) => {
|
||||
if (key === "teamUpgradeBanner") {
|
||||
const Banner = BannerComponent[key];
|
||||
|
||||
@@ -1,30 +1,48 @@
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { useSession } from "next-auth/react";
|
||||
|
||||
import {
|
||||
APP_NAME,
|
||||
FUTURE_ROUTES_OVERRIDE_COOKIE_NAME as COOKIE_NAME,
|
||||
IS_CALCOM,
|
||||
} from "@calcom/lib/constants";
|
||||
import { TopBanner } from "@calcom/ui";
|
||||
|
||||
/** Repurposing this component so we can opt-in and out from app router */
|
||||
function UserV2OptInBanner() {
|
||||
const session = useSession();
|
||||
|
||||
// Only show on client-side
|
||||
if (typeof document === "undefined") return null;
|
||||
// Only Admins can opt-in for now
|
||||
if (session.data?.user.role !== "ADMIN") return null;
|
||||
// Only Cal.com ADMINs can opt-in for now, also show on dev
|
||||
if (process.env.NODE_ENV === "production" && !IS_CALCOM) return null;
|
||||
|
||||
const hasV2OptInCookie = document.cookie.includes("calcom-v2-early-access=1");
|
||||
const hasV2OptInCookie = document.cookie.includes(`${COOKIE_NAME}=1`);
|
||||
|
||||
if (hasV2OptInCookie)
|
||||
return (
|
||||
<p className="text-muted text-xs">
|
||||
You're using the new version of {APP_NAME}.{" "}
|
||||
<a href="/api/v2-opt-in" className="text-blue-400 underline">
|
||||
Go back
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<TopBanner
|
||||
text={`You're using the future version of ${APP_NAME}.`}
|
||||
variant="warning"
|
||||
actions={
|
||||
<a href="/api/future-opt-in" className="border-b border-b-black">
|
||||
Go back
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<p className="text-muted text-xs">
|
||||
Want to try the new version of {APP_NAME}?{" "}
|
||||
<a href="/api/v2-opt-in" className="text-blue-400 underline">
|
||||
Opt-in to our v2.0 beta
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<TopBanner
|
||||
text={`Want to try the future version of ${APP_NAME}? (Only Cal.com admins can see this)`}
|
||||
variant="warning"
|
||||
actions={
|
||||
<a href="/api/future-opt-in" className="border-b border-b-black">
|
||||
Opt-in to future routes
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,8 @@ export const IS_PREMIUM_USERNAME_ENABLED =
|
||||
export const MAX_NB_INVITES = 100;
|
||||
|
||||
export const URL_PROTOCOL_REGEX = /(^\w+:|^)\/\//;
|
||||
export const FUTURE_ROUTES_OVERRIDE_COOKIE_NAME = "x-calcom-future-routes-override";
|
||||
export const FUTURE_ROUTES_ENABLED_COOKIE_NAME = "x-calcom-future-routes-enabled";
|
||||
|
||||
export const IS_VISUAL_REGRESSION_TESTING = Boolean(globalThis.window?.Meticulous?.isRunningAsTest);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user