Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ type RouteActionSelectorProps = {
fieldIdentifiers?: string[];
};

const EMPTY_FIELD_IDENTIFIERS: string[] = [];

const RouteActionSelector = ({
action,
onActionChange,
Expand All @@ -373,7 +375,7 @@ const RouteActionSelector = ({
customEventTypeSlug = "",
onCustomEventTypeSlugChange,
eventTypePrefix = "",
fieldIdentifiers = [],
fieldIdentifiers = EMPTY_FIELD_IDENTIFIERS,
}: RouteActionSelectorProps) => {
const { t } = useLocale();
return (
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/(use-page-wrapper)/payment/[uid]/PaymentPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ const BtcpayPaymentComponent = dynamic(

const PaymentPage: FC<PaymentPageProps> = (props) => {
const { t, i18n } = useLocale();
const [is24h, setIs24h] = useState(isBrowserLocale24h());
const [date, setDate] = useState(dayjs.utc(props.booking.startTime));
const [is24h, setIs24h] = useState(() => isBrowserLocale24h());
const [date, setDate] = useState(() => dayjs.utc(props.booking.startTime));
const [timezone, setTimezone] = useState<string | null>(null);
useTheme(props.profile.theme);
const isEmbed = useIsEmbed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function AdvancedPermissionGroup({
setIsExpanded(!isExpanded);
}
}}>
<div className="flex items-center gap-1.5" onClick={() => setIsExpanded(!isExpanded)}>
<div role="presentation" className="flex items-center gap-1.5" onClick={() => setIsExpanded(!isExpanded)}>
<ChevronRightIcon
className={classNames(
"h-4 w-4 transition-transform",
Expand All @@ -113,11 +113,13 @@ export function AdvancedPermissionGroup({
disabled={disabled}
/>
<span
role="presentation"
className="text-default cursor-pointer text-sm font-medium leading-none"
onClick={() => setIsExpanded(!isExpanded)}>
{t(resourceConfig?._resource?.i18nKey || "")}
</span>
<span
role="presentation"
className="text-muted cursor-pointer text-sm font-medium leading-none"
onClick={() => setIsExpanded(!isExpanded)}>
{t("all_permissions")}
Expand All @@ -126,8 +128,9 @@ export function AdvancedPermissionGroup({
</button>
{isExpanded && !isAllResources && (
<div
role="presentation"
className="bg-default border-muted m-1 flex flex-col gap-2.5 rounded-xl border p-3"
onClick={(e) => e.stopPropagation()} // Stop clicks in the permission list from affecting parent
onClick={(e) => e.stopPropagation()}
>
{resourceConfig &&
Object.entries(resourceConfig).map(([action, actionConfig]) => {
Expand Down Expand Up @@ -155,8 +158,9 @@ export function AdvancedPermissionGroup({
disabled={disabled}
/>
<div
role="presentation"
className="flex items-center gap-2"
onClick={(e) => e.stopPropagation()} // Stop label clicks from affecting parent
onClick={(e) => e.stopPropagation()}
>
<Label htmlFor={permission} className="mb-0">
<span className={classNames(isAutoEnabled && "text-muted-foreground")}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use client";

import { motion } from "framer-motion";
import { LazyMotion, domAnimation, m } from "framer-motion";

interface FingerprintAnimationProps {
isHovered: boolean;
}

export function FingerprintAnimation({ isHovered }: FingerprintAnimationProps) {
return (
<LazyMotion features={domAnimation}>
<div className="size-32 relative mx-auto flex aspect-square rounded-full border before:absolute before:-inset-2 before:rounded-full before:border dark:border-white/10 dark:before:border-white/5">
<svg className="m-auto h-fit w-24" viewBox="0 0 212 143" fill="none" xmlns="http://www.w3.org/2000/svg">
{/*Fingerprint*/}
Expand All @@ -25,7 +26,7 @@ export function FingerprintAnimation({ isHovered }: FingerprintAnimationProps) {
</g>

{/* Animated scanning line */}
<motion.path
<m.path
className="text-emphasis"
d="M48 0H164"
stroke="currentColor"
Expand Down Expand Up @@ -59,5 +60,6 @@ export function FingerprintAnimation({ isHovered }: FingerprintAnimationProps) {
</defs>
</svg>
</div>
</LazyMotion>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useRef, useState } from "react";
import { useRef } from "react";

import { useLocale } from "@calcom/lib/hooks/useLocale";

Expand All @@ -12,13 +12,10 @@ export interface RoleColorPickerProps {

export default function RoleColorPicker({ value, onChange, disabled }: RoleColorPickerProps) {
const { t } = useLocale();
const [, setCustomColor] = useState(value);
const colorInputRef = useRef<HTMLInputElement>(null);

const handleCustomColorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newColor = e.target.value;
setCustomColor(newColor);
onChange(newColor);
onChange(e.target.value);
};

const handleColorSquareClick = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,21 @@ function RoleItem({

return (
<div
role="button"
tabIndex={0}
className={classNames(
"border-subtle flex p-3",
(canUpdate && role.type !== "SYSTEM") || role.type === "SYSTEM"
? "hover:bg-subtle cursor-pointer"
: ""
)}
onClick={onClick}>
onClick={onClick}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
onClick();
}
}}>
<div className="flex w-full items-center gap-3 truncate">
{/* Icon */}
<div className="flex items-center justify-center">
Expand All @@ -161,7 +169,7 @@ function RoleItem({
</Badge>

{showDropdown && (
<div className="ml-auto" onClick={(e) => e.stopPropagation()}>
<div role="presentation" className="ml-auto" onClick={(e) => e.stopPropagation()}>
<Dropdown>
<DropdownMenuTrigger asChild>
<Button variant="icon" color="secondary" StartIcon="ellipsis" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,13 @@ const Page = async ({
params: Promise<{ id: string }>;
searchParams: Record<string, string | string[] | undefined>;
}) => {
const t = await getTranslate();
const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });
const { id: teamId } = await params;
const [t, session, { id: teamId }] = await Promise.all([
getTranslate(),
Promise.all([headers(), cookies()]).then(([h, c]) =>
getServerSession({ req: buildLegacyRequest(h, c) })
),
params,
]);

if (!session?.user?.id) {
return notFound();
Expand Down
19 changes: 5 additions & 14 deletions apps/web/app/(use-page-wrapper)/workflow/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const Page = async ({ searchParams }: PageProps) => {

const template = WORKFLOW_TEMPLATES[templateWorkflowId as keyof typeof WORKFLOW_TEMPLATES];

let redirectTarget: string;
try {
const workflow: Workflow = await prisma.workflow.create({
data: {
Expand All @@ -116,23 +117,13 @@ const Page = async ({ searchParams }: PageProps) => {
},
});

const redirectUrl = `/workflows/${workflow.id}?autoCreateAgent=true&templateWorkflowId=${templateWorkflowId}`;

redirect(redirectUrl);
redirectTarget = `/workflows/${workflow.id}?autoCreateAgent=true&templateWorkflowId=${templateWorkflowId}`;
} catch (error) {
if (
error &&
typeof error === "object" &&
"digest" in error &&
typeof error.digest === "string" &&
error.digest.startsWith("NEXT_REDIRECT")
) {
throw error;
}

console.error("Failed to create Cal.ai workflow:", error);
redirect("/workflows?error=failed-to-create-workflow");
redirectTarget = "/workflows?error=failed-to-create-workflow";
}

redirect(redirectTarget);
};

export default Page;
7 changes: 5 additions & 2 deletions apps/web/app/SpeculationRules.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import Script from "next/script";

const EMPTY_PREFETCH_PATHS: string[] = [];
const EMPTY_PRERENDER_PATHS: string[] = [];

export function SpeculationRules({
prefetchPathsOnHover = [],
prerenderPathsOnHover = [],
prefetchPathsOnHover = EMPTY_PREFETCH_PATHS,
prerenderPathsOnHover = EMPTY_PRERENDER_PATHS,
}: {
prefetchPathsOnHover?: string[];
prerenderPathsOnHover?: string[];
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/global-error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const GlobalError: NextPage<ErrorProps> = (props) => {
Sentry.captureException(props.error);
}, [props.error]);
return (
<html>
<html lang="en">
<body>
<CustomError {...props} />
</body>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/components/apps/AppPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export const AppPage = ({
<div
key={`iframe-${index}`}
className="mr-4 max-h-full min-h-[315px] min-w-[90%] max-w-full snap-center overflow-hidden rounded-md last:mb-0 lg:mb-4 lg:mr-0 [&_iframe]:h-full [&_iframe]:min-h-[315px] [&_iframe]:w-full">
<iframe allowFullScreen {...descriptionItem.iframe} />
<iframe allowFullScreen title="App content" {...descriptionItem.iframe} />
</div>
) : (
// eslint-disable-next-line @next/next/no-img-element -- external app screenshots with unknown dimensions
Expand Down
11 changes: 11 additions & 0 deletions apps/web/components/apps/installation/AccountsStepCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const AccountSelector: FC<AccountSelectorProps> = ({
const [selected, setSelected] = useState(false);
return (
<div
role="button"
tabIndex={0}
className={classNames(
"hover:bg-cal-muted flex cursor-pointer flex-row items-center gap-2 p-1",
(alreadyInstalled || loading) && "cursor-not-allowed",
Expand All @@ -52,6 +54,15 @@ const AccountSelector: FC<AccountSelectorProps> = ({
setSelected(true);
onClick();
}
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
if (!alreadyInstalled && !loading && onClick) {
setSelected(true);
onClick();
}
}
}}>
<Avatar
alt={avatar || ""}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ const ConfigureStepCardContent: FC<ConfigureStepCardProps> = (props) => {

const mainForSubmitRef = useRef<HTMLButtonElement>(null);
const [updatedEventTypesStatus, setUpdatedEventTypesStatus] = useState<TUpdatedEventTypesStatus>(
eventTypeGroups.reduce((arr: Array<{ id: number; updated: boolean }[]>, field) => {
() => eventTypeGroups.reduce((arr: Array<{ id: number; updated: boolean }[]>, field) => {
const selectedEventTypes = field.eventTypes
.filter((eventType) => eventType.selected)
.map((eventType) => ({ id: eventType.id as number, updated: false }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,18 @@ const LocationsWrapper = ({
);
};

const SkeletonLoader = () => {
return (
<SkeletonContainer>
<SkeletonText className="my-2 h-8 w-full" />
</SkeletonContainer>
);
};

const EventTypeConferencingAppSettings = ({ eventType, slug }: { eventType: TEventType; slug: string }) => {
const locationsQuery = trpc.viewer.apps.locationOptions.useQuery({});
const { t } = useLocale();

const SkeletonLoader = () => {
return (
<SkeletonContainer>
<SkeletonText className="my-2 h-8 w-full" />
</SkeletonContainer>
);
};

return (
<QueryCell
query={locationsQuery}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const EventTypeCard: FC<EventTypeCardProps> = ({
: [length];
return (
<div
role="presentation"
data-testid={`select-event-type-${id}`}
className="hover:bg-cal-muted min-h-20 box-border flex w-full cursor-pointer select-none items-center space-x-4 px-4 py-3"
onClick={() => handleSelect()}>
Expand Down
11 changes: 9 additions & 2 deletions apps/web/components/apps/routing-forms/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,13 +284,20 @@ export function Header({
onKeyDown={handleKeyDown}
onBlur={handleTitleSubmit}
className="text-default h-auto w-full whitespace-nowrap border-none p-0 text-sm font-semibold leading-none focus:ring-0"
autoFocus
/>
) : (
<div className="group flex items-center gap-1">
<span
role="button"
tabIndex={0}
className="text-default hover:bg-cal-muted min-w-0 cursor-pointer truncate whitespace-nowrap rounded px-1 text-sm font-semibold leading-none"
onClick={() => setIsEditing(true)}>
onClick={() => setIsEditing(true)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
setIsEditing(true);
}
}}>
{watchedName || "Loading..."}
</span>
<Button
Expand Down
14 changes: 7 additions & 7 deletions apps/web/components/apps/routing-forms/SingleForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { AnimatePresence, motion } from "framer-motion";
import { AnimatePresence, LazyMotion, domAnimation, m } from "framer-motion";
import { useEffect, useState } from "react";
import { useFormContext } from "react-hook-form";
import type { UseFormReturn } from "react-hook-form";
Expand Down Expand Up @@ -165,7 +165,7 @@ function SingleForm({
};

return (
<>
<LazyMotion features={domAnimation}>
<Form form={hookForm} handleSubmit={handleSubmit}>
<FormActionsProvider
appUrl={appUrl}
Expand All @@ -190,20 +190,20 @@ function SingleForm({
!isDesktop && "flex flex-col"
)}>
{isDesktop ? (
<motion.div
<m.div
layout
className="mx-auto w-full max-w-4xl px-3 lg:px-4 xl:px-0"
transition={{ duration: 0.3, ease: "easeInOut" }}>
<Page hookForm={hookForm} form={form} appUrl={appUrl} />
</motion.div>
</m.div>
) : (
<div className="mx-auto w-full max-w-4xl px-2">
<Page hookForm={hookForm} form={form} appUrl={appUrl} />
</div>
)}
<AnimatePresence>
{isTestPreviewOpen && isDesktop ? (
<motion.div
<m.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 20 }}
Expand All @@ -214,7 +214,7 @@ function SingleForm({
isTestPreviewOpen={isTestPreviewOpen}
setIsTestPreviewOpen={setIsTestPreviewOpen}
/>
</motion.div>
</m.div>
) : isTestPreviewOpen ? (
<div>
<TestFormRenderer
Expand Down Expand Up @@ -242,7 +242,7 @@ function SingleForm({
/>
)}
</Form>
</>
</LazyMotion>
);
}

Expand Down
Loading