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:
Omar López
2024-01-29 13:20:01 -07:00
committed by GitHub
co-authored by Peer Richelsen Keith Williams
parent fdaa6961f8
commit a0a731b357
5 changed files with 79 additions and 19 deletions
+2 -3
View File
@@ -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 =
+39
View File
@@ -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) }),
});
+2
View File
@@ -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&apos;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>
}
/>
);
}
+2
View File
@@ -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);