feat: enforce log in cal video (#21082)

* feat: enforce log in cal video

* chore: remove un necessary text

* fix: type err

* fix: pass user name
This commit is contained in:
Udit Takkar
2025-05-08 12:37:50 +00:00
committed by GitHub
parent b6ff64ed74
commit b73a3aeb0c
6 changed files with 93 additions and 1 deletions
@@ -7,6 +7,7 @@ import {
updateMeetingTokenIfExpired,
} from "@calcom/app-store/dailyvideo/lib/VideoApiAdapter";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { getCalVideoReference } from "@calcom/features/get-cal-video-reference";
import { CAL_VIDEO_MEETING_LINK_FOR_TESTING } from "@calcom/lib/constants";
import { isENVDev } from "@calcom/lib/env";
@@ -135,6 +136,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
const videoReference = getCalVideoReference(bookingObj.references);
const featureRepo = new FeaturesRepository();
const displayLogInOverlay = profile?.organizationId
? await featureRepo.checkIfTeamHasFeature(profile.organizationId, "cal-video-log-in-overlay")
: false;
return {
props: {
meetingUrl: videoReference.meetingUrl ?? "",
@@ -153,6 +159,8 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
},
hasTeamPlan: !!hasTeamPlan,
calVideoLogo,
displayLogInOverlay,
loggedInUserName: sessionUserId ? session?.user?.name : undefined,
},
};
}
@@ -7,12 +7,15 @@ import { useState, useEffect, useRef } from "react";
import dayjs from "@calcom/dayjs";
import { WEBSITE_URL } from "@calcom/lib/constants";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { TRANSCRIPTION_STOPPED_ICON, RECORDING_DEFAULT_ICON } from "@calcom/lib/constants";
import { formatToLocalizedDate, formatToLocalizedTime } from "@calcom/lib/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
import classNames from "@calcom/ui/classNames";
import { Button } from "@calcom/ui/components/button";
import { Dialog, DialogContent } from "@calcom/ui/components/dialog";
import { Icon } from "@calcom/ui/components/icon";
import type { getServerSideProps } from "@lib/video/[uid]/getServerSideProps";
@@ -22,7 +25,15 @@ import { CalAiTranscribe } from "~/videos/ai/ai-transcribe";
export type PageProps = inferSSRProps<typeof getServerSideProps>;
export default function JoinCall(props: PageProps) {
const { meetingUrl, meetingPassword, booking, hasTeamPlan, calVideoLogo } = props;
const {
meetingUrl,
meetingPassword,
booking,
hasTeamPlan,
calVideoLogo,
displayLogInOverlay,
loggedInUserName,
} = props;
const [daily, setDaily] = useState<DailyCall | null>(null);
useEffect(() => {
@@ -50,6 +61,7 @@ export default function JoinCall(props: PageProps) {
height: "100%",
},
url: meetingUrl,
userName: loggedInUserName ? loggedInUserName ?? undefined : undefined,
...(typeof meetingPassword === "string" && { token: meetingPassword }),
...(hasTeamPlan && {
customTrayButtons: {
@@ -112,6 +124,8 @@ export default function JoinCall(props: PageProps) {
/>
)}
</div>
{displayLogInOverlay && <LogInOverlay isLoggedIn={!!loggedInUserName} bookingUid={booking.uid} />}
<VideoMeetingInfo booking={booking} />
</DailyProvider>
);
@@ -187,6 +201,58 @@ function ProgressBar(props: ProgressBarProps) {
);
}
interface LogInOverlayProps {
isLoggedIn: boolean;
bookingUid: string;
}
export function LogInOverlay(props: LogInOverlayProps) {
const { t } = useLocale();
const { isLoggedIn, bookingUid } = props;
const [open, setOpen] = useState(!isLoggedIn);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent
title={t("join_video_call")}
description={t("choose_how_you_d_like_to_join_call")}
className="bg-black text-white sm:max-w-[480px]">
<div className="pb-8">
<div className="space-y-8">
<Button color="primary" className="mt-4 w-full justify-center " onClick={() => setOpen(false)}>
{t("continue_as_guest")}
</Button>
{/* Divider */}
<div className="relative py-2">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t border-gray-600" />
</div>
<div className="relative flex justify-center">
<span className="bg-black px-4 text-sm text-gray-400">{t("or")}</span>
</div>
</div>
<div className="space-y-3">
<h4 className="text-lg font-semibold text-white">{t("sign_in_to_cal_com")}</h4>
<p className="text-sm text-gray-300">{t("track_your_meetings")}</p>
<Button
color="primary"
className="mt-4 w-full justify-center"
onClick={() =>
(window.location.href = `${WEBAPP_URL}/auth/login?callbackUrl=${WEBAPP_URL}/video/${bookingUid}`)
}>
<Icon name="external-link" className="mr-2 h-4 w-4" />
{t("log_in_to_cal_com")}
</Button>
</div>
</div>
</div>
</DialogContent>
</Dialog>
);
}
interface VideoMeetingInfo {
booking: PageProps["booking"];
}
@@ -620,6 +620,7 @@
"your_full_name": "Your full name",
"no_name": "No name",
"enter_number_between_range": "Please enter a number between 1 and {{maxOccurences}}",
"continue_as_guest_description": "Quick and easy - no account required. Perfect for one-time meetings.",
"email_address": "Email address",
"enter_valid_email": "Please enter a valid email",
"please_schedule_future_call": " Please schedule a future call if we're not available in {{seconds}} seconds",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "In Person (Attendee Address)",
"somewhere_else": "Somewhere Else",
"custom_attendee_location": "Custom attendee location",
"continue_as_guest": "Continue as Guest",
"any_location": "Any location",
"yes": "Yes",
"no": "No",
@@ -1297,6 +1299,11 @@
"event_cancelled_trigger": "when event is canceled",
"after_hosts_cal_video_no_show": "After hosts didn't join cal video",
"after_guests_cal_video_no_show": "After guests didn't join cal video",
"join_video_call": "Join the video call",
"sign_in_to_cal_com": "Sign in to your Cal.com account",
"log_in_to_cal_com": "Log in to Cal.com",
"track_your_meetings": "Track your meetings, get notifications, and manage your schedule more effectively.",
"choose_how_you_d_like_to_join_call": "Choose how you'd like to join this call",
"new_event_trigger": "when new event is booked",
"email_host_action": "send email to host",
"email_attendee_action": "send email to attendees",
+1
View File
@@ -18,4 +18,5 @@ export type AppFlags = {
"organizer-request-email-v2": boolean;
"delegation-credential": boolean;
"salesforce-crm-tasker": boolean;
"cal-video-log-in-overlay": boolean;
};
+1
View File
@@ -17,6 +17,7 @@ const initialData: AppFlags = {
"organizer-request-email-v2": false,
"delegation-credential": false,
"salesforce-crm-tasker": false,
"cal-video-log-in-overlay": false,
};
if (process.env.NEXT_PUBLIC_IS_E2E) {
@@ -0,0 +1,9 @@
INSERT INTO
"Feature" (slug, enabled, description, "type")
VALUES
(
'cal-video-log-in-overlay',
false,
'Enable Log In Overlay - Allows system to show a log in overlay on the Cal Video page.',
'OPERATIONAL'
) ON CONFLICT (slug) DO NOTHING;