Compare commits

...
21 Commits
Author SHA1 Message Date
Alex van Andel 865663646a v2.5.5
release.yml / release (push) Canceled after 0s
2023-01-24 16:54:35 +00:00
Alex van Andel b7c92063c2 Revert "v2.5.4"
This reverts commit 4f293edb6b.
2023-01-24 16:54:05 +00:00
Alex van Andel 4f293edb6b v2.5.4 2023-01-24 16:52:33 +00:00
Ben HybertandAlex van Andel 0c88cf75e0 corrected avatars inside users block (#6667)
* corrected avatars inside users block

* ensured the team avatar didnt shrink too

* Update packages/ui/components/avatar/Avatar.tsx

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2023-01-24 16:10:43 +00:00
Nafees NazikandUdit Takkar 0b93647209 fix: double border issue in Location Select (#6646)
* fix: border issue

* fix: remove border from dropdown

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-01-24 17:05:35 +01:00
Alex van Andel b931b00714 Add env variables to turbo.json relevant to the website build (#6654) 2023-01-24 15:47:46 +00:00
Nafees Nazik 796a5f8d51 feat: use cal video as the default location (#6643)
* feat: use cal video as default while creating new events

* feat: use cal video as default value

* chore: remove default value

* fix: default value logic

* chore: remove console.log
2023-01-24 15:28:40 +00:00
sean-brydon 905a110377 Invites (#6665) 2023-01-24 15:27:05 +00:00
Alex van Andel 6ccc19985f Add sizePropsBySize to avatarPrimitive root (#6666) 2023-01-24 14:01:27 +00:00
Udit Takkar 8f71474303 fix: add allowOverflow property (#6636)
* fix: add allowOverlfow property

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: date override input dialog

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-01-24 14:00:45 +00:00
zomars 5f351230ff Ignores auth submodule 2023-01-23 16:50:17 -07:00
Alex van Andel 3e005919c1 Only return enabled apps in getEnabledApps (#6653) 2023-01-23 16:27:20 -07:00
cfa8fd8b67 Reduce bundle size by importing single icons at a time (#6644)
* Removed barrel import for icons to reduce bundle size.

* Fixed replacement mistakes

* Reverted unneccesary yarn.lock updates

* Added some missed Icon. import conversions

* Remove merge artifact import in @calcom/ui

* Don't import Icon in pages/[user]

* Update packages/ui/package.json

Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Omar López <zomars@me.com>
2023-01-23 23:08:01 +00:00
Alex van Andel a888be6e04 Support both https/git by detection of origin root (#6651)
* Support both https/git by detection of origin root

* Remove unnecessary .

* Minor comment fixup
2023-01-23 23:05:53 +00:00
Joe Au-Yeung 6aa2cba3ce Msteams access token refresh (#6607)
* Add is valid call

* WIP

* Change logic for Microsoft refresh token

* remove async
2023-01-23 15:36:24 -07:00
sean-brydon 12ab615684 Fix weird avatar issue (#6645) 2023-01-23 15:48:40 +00:00
1d792a2c6c generic <UpgradeScreen> component (#6594)
* first attempt of <UpgradeScreen>

* changes to icons

* reverted changes back to initial state, needs fix: teams not showing

* WIP

* Fix weird reactnode error

* Fix loading text

* added upgradeTip to routing forms

* icon colors

* create and use hook to check if user has team plan

* use useTeamPlan for upgradeTeamsBadge

* replace huge svg with compressed jpeg

* responsive fixes

* Update packages/ui/components/badge/UpgradeTeamsBadge.tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Give team plan features to E2E tests

* Allow option to make a user part of team int ests

* Remove flash of paywall for team user

* Add team user for typeform tests as well

Co-authored-by: Peer Richelsen <peer@cal.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2023-01-23 10:58:41 +01:00
Hariom Balhara 9602ac29fb Fix Ga4 tracking (#6630) 2023-01-23 09:09:16 +00:00
Leo Giovanetti 5714471b9a Temporary fix (#6626)
release.yml / release (push) Canceled after 0s
2023-01-22 17:27:27 +00:00
Mohammed CherfaouiandAlex van Andel a99e93a4bd fix tooltip and modal stacking issues (#6491)
* fix tooltip and modal stacking issues

* use z-index in larger screens and less

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2023-01-22 20:31:25 +05:30
Udit Takkar 7f044ff92f fix: use items-center (#6618) 2023-01-22 13:36:07 +01:00
181 changed files with 1404 additions and 1055 deletions

No files matched your search

+1
View File
@@ -86,3 +86,4 @@ apps/storybook/build-storybook.log
apps/api apps/api
apps/website apps/website
apps/console apps/console
apps/auth
+2 -2
View File
@@ -1,7 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon } from "@calcom/ui"; import { FiX } from "@calcom/ui/components/icon";
export default function AddToHomescreen() { export default function AddToHomescreen() {
const { t } = useLocale(); const { t } = useLocale();
@@ -40,7 +40,7 @@ export default function AddToHomescreen() {
type="button" type="button"
className="-mr-1 flex rounded-md p-2 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-white"> className="-mr-1 flex rounded-md p-2 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-white">
<span className="sr-only">{t("dismiss")}</span> <span className="sr-only">{t("dismiss")}</span>
<Icon.FiX className="h-6 w-6 text-white" aria-hidden="true" /> <FiX className="h-6 w-6 text-white" aria-hidden="true" />
</button> </button>
</div> </div>
</div> </div>
+8 -8
View File
@@ -12,7 +12,6 @@ import {
DialogClose, DialogClose,
DialogContent, DialogContent,
HorizontalTabs, HorizontalTabs,
Icon,
InputLeading, InputLeading,
Label, Label,
showToast, showToast,
@@ -20,6 +19,7 @@ import {
TextArea, TextArea,
TextField, TextField,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiCode, FiTrello, FiSun, FiArrowLeft, FiChevronRight } from "@calcom/ui/components/icon";
import ColorPicker from "@components/ui/colorpicker"; import ColorPicker from "@components/ui/colorpicker";
import Select from "@components/ui/form/Select"; import Select from "@components/ui/form/Select";
@@ -488,7 +488,7 @@ const tabs = [
{ {
name: "HTML", name: "HTML",
href: "embedTabName=embed-code", href: "embedTabName=embed-code",
icon: Icon.FiCode, icon: FiCode,
type: "code", type: "code",
Component: forwardRef< Component: forwardRef<
HTMLTextAreaElement | HTMLIFrameElement | null, HTMLTextAreaElement | HTMLIFrameElement | null,
@@ -541,7 +541,7 @@ ${getEmbedTypeSpecificString({ embedFramework: "HTML", embedType, calLink, previ
{ {
name: "React", name: "React",
href: "embedTabName=embed-react", href: "embedTabName=embed-react",
icon: Icon.FiCode, icon: FiCode,
type: "code", type: "code",
Component: forwardRef< Component: forwardRef<
HTMLTextAreaElement | HTMLIFrameElement | null, HTMLTextAreaElement | HTMLIFrameElement | null,
@@ -581,7 +581,7 @@ ${getEmbedTypeSpecificString({ embedFramework: "react", embedType, calLink, prev
{ {
name: "Preview", name: "Preview",
href: "embedTabName=embed-preview", href: "embedTabName=embed-preview",
icon: Icon.FiTrello, icon: FiTrello,
type: "iframe", type: "iframe",
Component: forwardRef< Component: forwardRef<
HTMLIFrameElement | HTMLTextAreaElement | null, HTMLIFrameElement | HTMLTextAreaElement | null,
@@ -617,7 +617,7 @@ Cal("init", {origin:"${WEBAPP_URL}"});
const ThemeSelectControl = ({ children, ...props }: ControlProps<{ value: Theme; label: string }, false>) => { const ThemeSelectControl = ({ children, ...props }: ControlProps<{ value: Theme; label: string }, false>) => {
return ( return (
<components.Control {...props}> <components.Control {...props}>
<Icon.FiSun className="ml-2 h-4 w-4 text-gray-500" /> <FiSun className="ml-2 h-4 w-4 text-gray-500" />
{children} {children}
</components.Control> </components.Control>
); );
@@ -815,7 +815,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
onClick={() => { onClick={() => {
removeQueryParams(router, ["embedType", "embedTabName"]); removeQueryParams(router, ["embedType", "embedTabName"]);
}}> }}>
<Icon.FiArrowLeft className="mr-4 w-4" /> <FiArrowLeft className="mr-4 w-4" />
</button> </button>
{embed.title} {embed.title}
</h3> </h3>
@@ -835,7 +835,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
? "Floating Popup Customization" ? "Floating Popup Customization"
: "Element Click Customization"} : "Element Click Customization"}
</div> </div>
<Icon.FiChevronRight <FiChevronRight
className={`${ className={`${
isEmbedCustomizationOpen ? "rotate-90 transform" : "" isEmbedCustomizationOpen ? "rotate-90 transform" : ""
} ml-auto h-5 w-5 text-gray-500`} } ml-auto h-5 w-5 text-gray-500`}
@@ -1002,7 +1002,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
onOpenChange={() => setIsBookingCustomizationOpen((val) => !val)}> onOpenChange={() => setIsBookingCustomizationOpen((val) => !val)}>
<CollapsibleTrigger className="flex w-full" type="button"> <CollapsibleTrigger className="flex w-full" type="button">
<div className="text-base font-medium text-gray-900">Cal Booking Customization</div> <div className="text-base font-medium text-gray-900">Cal Booking Customization</div>
<Icon.FiChevronRight <FiChevronRight
className={`${ className={`${
isBookingCustomizationOpen ? "rotate-90 transform" : "" isBookingCustomizationOpen ? "rotate-90 transform" : ""
} ml-auto h-5 w-5 text-gray-500`} } ml-auto h-5 w-5 text-gray-500`}
+8 -7
View File
@@ -1,7 +1,8 @@
import React, { ComponentProps } from "react"; import React, { ComponentProps } from "react";
import Shell from "@calcom/features/shell/Shell"; import Shell from "@calcom/features/shell/Shell";
import { ErrorBoundary, Icon } from "@calcom/ui"; import { ErrorBoundary } from "@calcom/ui";
import { FiCreditCard, FiKey, FiLock, FiTerminal, FiUser, FiUsers } from "@calcom/ui/components/icon";
import NavTabs from "./NavTabs"; import NavTabs from "./NavTabs";
@@ -9,32 +10,32 @@ const tabs = [
{ {
name: "profile", name: "profile",
href: "/settings/profile", href: "/settings/profile",
icon: Icon.FiUser, icon: FiUser,
}, },
{ {
name: "teams", name: "teams",
href: "/settings/teams", href: "/settings/teams",
icon: Icon.FiUsers, icon: FiUsers,
}, },
{ {
name: "security", name: "security",
href: "/settings/security", href: "/settings/security",
icon: Icon.FiKey, icon: FiKey,
}, },
{ {
name: "developer", name: "developer",
href: "/settings/developer", href: "/settings/developer",
icon: Icon.FiTerminal, icon: FiTerminal,
}, },
{ {
name: "billing", name: "billing",
href: "/settings/billing", href: "/settings/billing",
icon: Icon.FiCreditCard, icon: FiCreditCard,
}, },
{ {
name: "admin", name: "admin",
href: "/settings/admin", href: "/settings/admin",
icon: Icon.FiLock, icon: FiLock,
adminRequired: true, adminRequired: true,
}, },
]; ];
@@ -4,7 +4,8 @@ import { InstallAppButton } from "@calcom/app-store/components";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import type { App } from "@calcom/types/App"; import type { App } from "@calcom/types/App";
import { Button, Icon, Select } from "@calcom/ui"; import { Button, Select } from "@calcom/ui";
import { FiPlus } from "@calcom/ui/components/icon";
import { QueryCell } from "@lib/QueryCell"; import { QueryCell } from "@lib/QueryCell";
@@ -31,7 +32,7 @@ const ImageOption = (optionProps: OptionProps<{ [key: string]: string; type: App
/> />
) : ( ) : (
<Button className="w-full" color="minimal" href="/apps/categories/calendar"> <Button className="w-full" color="minimal" href="/apps/categories/calendar">
<Icon.FiPlus className="text-color mr-3 ml-1 h-4 w-4" /> <FiPlus className="text-color mr-3 ml-1 h-4 w-4" />
<p>{t("install_new_calendar_app")}</p> <p>{t("install_new_calendar_app")}</p>
</Button> </Button>
); );
@@ -61,7 +62,7 @@ const AdditionalCalendarSelector = ({ isLoading }: AdditionalCalendarSelectorPro
<Select <Select
name="additionalCalendar" name="additionalCalendar"
placeholder={ placeholder={
<Button StartIcon={Icon.FiPlus} color="secondary"> <Button StartIcon={FiPlus} color="secondary">
{t("add")} {t("add")}
</Button> </Button>
} }
+19 -9
View File
@@ -12,7 +12,17 @@ import { APP_NAME, COMPANY_NAME, SUPPORT_MAIL_ADDRESS } from "@calcom/lib/consta
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { App as AppType } from "@calcom/types/App"; import { App as AppType } from "@calcom/types/App";
import { Button, Icon, showToast, SkeletonButton, SkeletonText, HeadSeo, Badge } from "@calcom/ui"; import { Button, showToast, SkeletonButton, SkeletonText, HeadSeo, Badge } from "@calcom/ui";
import {
FiBookOpen,
FiCheck,
FiExternalLink,
FiFile,
FiFlag,
FiMail,
FiPlus,
FiShield,
} from "@calcom/ui/components/icon";
const Component = ({ const Component = ({
name, name,
@@ -118,7 +128,7 @@ const Component = ({
isGlobal || isGlobal ||
(existingCredentials.length > 0 && allowedMultipleInstalls ? ( (existingCredentials.length > 0 && allowedMultipleInstalls ? (
<div className="flex space-x-3"> <div className="flex space-x-3">
<Button StartIcon={Icon.FiCheck} color="secondary" disabled> <Button StartIcon={FiCheck} color="secondary" disabled>
{existingCredentials.length > 0 {existingCredentials.length > 0
? t("active_install", { count: existingCredentials.length }) ? t("active_install", { count: existingCredentials.length })
: t("default")} : t("default")}
@@ -139,7 +149,7 @@ const Component = ({
} }
return ( return (
<Button <Button
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
{...props} {...props}
// @TODO: Overriding color and size prevent us from // @TODO: Overriding color and size prevent us from
// having to duplicate InstallAppButton for now. // having to duplicate InstallAppButton for now.
@@ -226,7 +236,7 @@ const Component = ({
rel="noreferrer" rel="noreferrer"
className="text-sm font-normal text-black no-underline hover:underline" className="text-sm font-normal text-black no-underline hover:underline"
href={docs}> href={docs}>
<Icon.FiBookOpen className="mr-1 -mt-1 inline h-4 w-4 text-gray-500" /> <FiBookOpen className="mr-1 -mt-1 inline h-4 w-4 text-gray-500" />
{t("documentation")} {t("documentation")}
</a> </a>
</li> </li>
@@ -238,7 +248,7 @@ const Component = ({
rel="noreferrer" rel="noreferrer"
className="font-normal text-black no-underline hover:underline" className="font-normal text-black no-underline hover:underline"
href={website}> href={website}>
<Icon.FiExternalLink className="mr-1 -mt-px inline h-4 w-4 text-gray-500" /> <FiExternalLink className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
{website.replace("https://", "")} {website.replace("https://", "")}
</a> </a>
</li> </li>
@@ -250,7 +260,7 @@ const Component = ({
rel="noreferrer" rel="noreferrer"
className="font-normal text-black no-underline hover:underline" className="font-normal text-black no-underline hover:underline"
href={"mailto:" + email}> href={"mailto:" + email}>
<Icon.FiMail className="mr-1 -mt-px inline h-4 w-4 text-gray-500" /> <FiMail className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
{email} {email}
</a> </a>
@@ -263,7 +273,7 @@ const Component = ({
rel="noreferrer" rel="noreferrer"
className="font-normal text-black no-underline hover:underline" className="font-normal text-black no-underline hover:underline"
href={tos}> href={tos}>
<Icon.FiFile className="mr-1 -mt-px inline h-4 w-4 text-gray-500" /> <FiFile className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
{t("terms_of_service")} {t("terms_of_service")}
</a> </a>
</li> </li>
@@ -275,7 +285,7 @@ const Component = ({
rel="noreferrer" rel="noreferrer"
className="font-normal text-black no-underline hover:underline" className="font-normal text-black no-underline hover:underline"
href={privacy}> href={privacy}>
<Icon.FiShield className="mr-1 -mt-px inline h-4 w-4 text-gray-500" /> <FiShield className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
{t("privacy_policy")} {t("privacy_policy")}
</a> </a>
</li> </li>
@@ -286,7 +296,7 @@ const Component = ({
{t("every_app_published", { appName: APP_NAME, companyName: COMPANY_NAME })} {t("every_app_published", { appName: APP_NAME, companyName: COMPANY_NAME })}
</span> </span>
<a className="mt-2 block text-xs text-red-500" href={`mailto:${SUPPORT_MAIL_ADDRESS}`}> <a className="mt-2 block text-xs text-red-500" href={`mailto:${SUPPORT_MAIL_ADDRESS}`}>
<Icon.FiFlag className="inline h-3 w-3" /> {t("report_app")} <FiFlag className="inline h-3 w-3" /> {t("report_app")}
</a> </a>
</div> </div>
</div> </div>
@@ -11,13 +11,13 @@ import {
Alert, Alert,
Button, Button,
EmptyScreen, EmptyScreen,
Icon,
List, List,
showToast, showToast,
AppSkeletonLoader as SkeletonLoader, AppSkeletonLoader as SkeletonLoader,
Switch, Switch,
ShellSubHeading, ShellSubHeading,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiArrowLeft, FiCalendar, FiPlus } from "@calcom/ui/components/icon";
import { QueryCell } from "@lib/QueryCell"; import { QueryCell } from "@lib/QueryCell";
@@ -100,7 +100,7 @@ function CalendarSwitch(props: {
/> />
{!!props.destination && ( {!!props.destination && (
<span className="ml-4 inline-flex items-center gap-1 rounded-md bg-gray-100 px-2 py-1 text-sm font-normal text-gray-800"> <span className="ml-4 inline-flex items-center gap-1 rounded-md bg-gray-100 px-2 py-1 text-sm font-normal text-gray-800">
<Icon.FiArrowLeft className="h-4 w-4" /> <FiArrowLeft className="h-4 w-4" />
{t("adding_events_to")} {t("adding_events_to")}
</span> </span>
)} )}
@@ -282,8 +282,8 @@ export function CalendarListContainer(props: { heading?: boolean; fromOnboarding
<div className="flex justify-between rounded-md border border-gray-200 bg-gray-50 p-4"> <div className="flex justify-between rounded-md border border-gray-200 bg-gray-50 p-4">
<div className="flex w-full flex-col items-start gap-4 md:flex-row md:items-center"> <div className="flex w-full flex-col items-start gap-4 md:flex-row md:items-center">
<div className="relative rounded-md border border-gray-200 bg-white p-1.5"> <div className="relative rounded-md border border-gray-200 bg-white p-1.5">
<Icon.FiCalendar className="h-8 w-8" strokeWidth="1" /> <FiCalendar className="h-8 w-8" strokeWidth="1" />
<Icon.FiPlus <FiPlus
className="absolute left-4 top-1/2 ml-0.5 mt-[1px] h-2 w-2 text-black" className="absolute left-4 top-1/2 ml-0.5 mt-[1px] h-2 w-2 text-black"
strokeWidth="4" strokeWidth="4"
/> />
@@ -322,7 +322,7 @@ export function CalendarListContainer(props: { heading?: boolean; fromOnboarding
</> </>
) : ( ) : (
<EmptyScreen <EmptyScreen
Icon={Icon.FiCalendar} Icon={FiCalendar}
headline={t("no_category_apps", { headline={t("no_category_apps", {
category: t("calendar").toLowerCase(), category: t("calendar").toLowerCase(),
})} })}
@@ -3,7 +3,8 @@ import { useRouter } from "next/router";
import { ReactNode, useEffect, useState } from "react"; import { ReactNode, useEffect, useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Badge, Icon, ListItem, ListItemText, ListItemTitle, showToast } from "@calcom/ui"; import { Badge, ListItem, ListItemText, ListItemTitle, showToast } from "@calcom/ui";
import { FiAlertCircle } from "@calcom/ui/components/icon";
import classNames from "@lib/classNames"; import classNames from "@lib/classNames";
@@ -63,7 +64,7 @@ function IntegrationListItem(props: {
{/* Alert error that key stopped working. */} {/* Alert error that key stopped working. */}
{props.invalidCredential && ( {props.invalidCredential && (
<div className="flex items-center space-x-2 rtl:space-x-reverse"> <div className="flex items-center space-x-2 rtl:space-x-reverse">
<Icon.FiAlertCircle className="w-8 text-red-500 sm:w-4" /> <FiAlertCircle className="w-8 text-red-500 sm:w-4" />
<ListItemText component="p" className="whitespace-pre-wrap text-red-500"> <ListItemText component="p" className="whitespace-pre-wrap text-red-500">
{t("invalid_credential")} {t("invalid_credential")}
</ListItemText> </ListItemText>
@@ -4,7 +4,8 @@ import React, { ComponentProps } from "react";
import Shell from "@calcom/features/shell/Shell"; import Shell from "@calcom/features/shell/Shell";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { EmptyScreen, Icon } from "@calcom/ui"; import { EmptyScreen } from "@calcom/ui";
import { FiAlertCircle } from "@calcom/ui/components/icon";
type AppsLayoutProps = { type AppsLayoutProps = {
children: React.ReactNode; children: React.ReactNode;
@@ -25,7 +26,7 @@ export default function AppsLayout({ children, actions, emptyStore, ...rest }: A
<main className="w-full"> <main className="w-full">
{emptyStore ? ( {emptyStore ? (
<EmptyScreen <EmptyScreen
Icon={Icon.FiAlertCircle} Icon={FiAlertCircle}
headline={t("no_apps")} headline={t("no_apps")}
description={session.data?.user.role === "ADMIN" ? "You can enable apps in the settings" : ""} description={session.data?.user.role === "ADMIN" ? "You can enable apps in the settings" : ""}
buttonText={session.data?.user.role === "ADMIN" ? t("apps_settings") : ""} buttonText={session.data?.user.role === "ADMIN" ? t("apps_settings") : ""}
@@ -4,39 +4,39 @@ import AppCategoryNavigation from "@calcom/app-store/_components/AppCategoryNavi
import { InstalledAppVariants } from "@calcom/app-store/utils"; import { InstalledAppVariants } from "@calcom/app-store/utils";
import Shell from "@calcom/features/shell/Shell"; import Shell from "@calcom/features/shell/Shell";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Icon } from "@calcom/ui";
import type { HorizontalTabItemProps, VerticalTabItemProps } from "@calcom/ui"; import type { HorizontalTabItemProps, VerticalTabItemProps } from "@calcom/ui";
import { FiBarChart, FiCalendar, FiCreditCard, FiGrid, FiShare2, FiVideo } from "@calcom/ui/components/icon";
const tabs: (VerticalTabItemProps | HorizontalTabItemProps)[] = [ const tabs: (VerticalTabItemProps | HorizontalTabItemProps)[] = [
{ {
name: "calendar", name: "calendar",
href: "/apps/installed/calendar", href: "/apps/installed/calendar",
icon: Icon.FiCalendar, icon: FiCalendar,
}, },
{ {
name: "conferencing", name: "conferencing",
href: "/apps/installed/conferencing", href: "/apps/installed/conferencing",
icon: Icon.FiVideo, icon: FiVideo,
}, },
{ {
name: "payment", name: "payment",
href: "/apps/installed/payment", href: "/apps/installed/payment",
icon: Icon.FiCreditCard, icon: FiCreditCard,
}, },
{ {
name: "automation", name: "automation",
href: "/apps/installed/automation", href: "/apps/installed/automation",
icon: Icon.FiShare2, icon: FiShare2,
}, },
{ {
name: "analytics", name: "analytics",
href: "/apps/installed/analytics", href: "/apps/installed/analytics",
icon: Icon.FiBarChart, icon: FiBarChart,
}, },
{ {
name: "other", name: "other",
href: "/apps/installed/other", href: "/apps/installed/other",
icon: Icon.FiGrid, icon: FiGrid,
}, },
]; ];
@@ -1,7 +1,8 @@
import { getEventLocationType, locationKeyToString } from "@calcom/app-store/locations"; import { getEventLocationType, locationKeyToString } from "@calcom/app-store/locations";
import { classNames } from "@calcom/lib"; import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon, Tooltip } from "@calcom/ui"; import { Tooltip } from "@calcom/ui";
import { FiLink } from "@calcom/ui/components/icon";
import { Props } from "./pages/AvailabilityPage"; import { Props } from "./pages/AvailabilityPage";
@@ -19,7 +20,7 @@ export function AvailableEventLocations({ locations }: { locations: Props["event
return ( return (
<div key={location.type} className="flex flex-row items-center text-sm font-medium"> <div key={location.type} className="flex flex-row items-center text-sm font-medium">
{eventLocationType.iconUrl === "/link.svg" ? ( {eventLocationType.iconUrl === "/link.svg" ? (
<Icon.FiLink className="dark:text-darkgray-600 ml-[2px] h-4 w-4 opacity-70 ltr:mr-[10px] rtl:ml-[10px] dark:opacity-100 " /> <FiLink className="dark:text-darkgray-600 ml-[2px] h-4 w-4 opacity-70 ltr:mr-[10px] rtl:ml-[10px] dark:opacity-100 " />
) : ( ) : (
<img <img
src={eventLocationType.iconUrl} src={eventLocationType.iconUrl}
@@ -4,7 +4,8 @@ import { FC, ReactNode, useEffect } from "react";
import dayjs from "@calcom/dayjs"; import dayjs from "@calcom/dayjs";
import { classNames } from "@calcom/lib"; import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon, Badge } from "@calcom/ui"; import { Badge } from "@calcom/ui";
import { FiCheckSquare, FiClock, FiInfo } from "@calcom/ui/components/icon";
import useRouterQuery from "@lib/hooks/useRouterQuery"; import useRouterQuery from "@lib/hooks/useRouterQuery";
@@ -93,7 +94,7 @@ const BookingDescription: FC<Props> = (props) => {
isBookingPage && "dark:text-darkgray-600 text-sm font-medium text-gray-600" isBookingPage && "dark:text-darkgray-600 text-sm font-medium text-gray-600"
)}> )}>
<div> <div>
<Icon.FiInfo <FiInfo
className={classNames( className={classNames(
"ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]", "ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]",
isBookingPage && "dark:text-darkgray-600 -mt-1 text-gray-500" isBookingPage && "dark:text-darkgray-600 -mt-1 text-gray-500"
@@ -112,7 +113,7 @@ const BookingDescription: FC<Props> = (props) => {
isBookingPage && "dark:text-darkgray-600 text-sm font-medium text-gray-600" isBookingPage && "dark:text-darkgray-600 text-sm font-medium text-gray-600"
)}> )}>
<div> <div>
<Icon.FiCheckSquare className="ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px] " /> <FiCheckSquare className="ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px] " />
</div> </div>
{requiresConfirmationText} {requiresConfirmationText}
</div> </div>
@@ -123,9 +124,10 @@ const BookingDescription: FC<Props> = (props) => {
<div <div
className={classNames( className={classNames(
"flex flex-nowrap text-sm font-medium", "flex flex-nowrap text-sm font-medium",
isBookingPage && "dark:text-darkgray-600 text-gray-600" isBookingPage && "dark:text-darkgray-600 text-gray-600",
!eventType.metadata?.multipleDuration && "items-center"
)}> )}>
<Icon.FiClock <FiClock
className={classNames( className={classNames(
"min-h-4 min-w-4 ml-[2px] inline-block ltr:mr-[10px] rtl:ml-[10px]", "min-h-4 min-w-4 ml-[2px] inline-block ltr:mr-[10px] rtl:ml-[10px]",
isBookingPage && "mt-[2px]" isBookingPage && "mt-[2px]"
@@ -18,7 +18,6 @@ import {
DialogContent, DialogContent,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
Icon,
MeetingTimeInTimezones, MeetingTimeInTimezones,
showToast, showToast,
TextArea, TextArea,
@@ -26,6 +25,7 @@ import {
ActionType, ActionType,
TableActions, TableActions,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiCheck, FiClock, FiMapPin, FiRefreshCcw, FiSend, FiSlash, FiX } from "@calcom/ui/components/icon";
import useMeQuery from "@lib/hooks/useMeQuery"; import useMeQuery from "@lib/hooks/useMeQuery";
@@ -100,7 +100,7 @@ function BookingListItem(booking: BookingItemProps) {
onClick: () => { onClick: () => {
setRejectionDialogIsOpen(true); setRejectionDialogIsOpen(true);
}, },
icon: Icon.FiSlash, icon: FiSlash,
disabled: mutation.isLoading, disabled: mutation.isLoading,
}, },
{ {
@@ -109,7 +109,7 @@ function BookingListItem(booking: BookingItemProps) {
onClick: () => { onClick: () => {
bookingConfirm(true); bookingConfirm(true);
}, },
icon: Icon.FiCheck, icon: FiCheck,
disabled: mutation.isLoading, disabled: mutation.isLoading,
color: "primary", color: "primary",
}, },
@@ -135,7 +135,7 @@ function BookingListItem(booking: BookingItemProps) {
href: `/booking/${booking.uid}?cancel=true${ href: `/booking/${booking.uid}?cancel=true${
isTabRecurring && isRecurring ? "&allRemainingBookings=true" : "" isTabRecurring && isRecurring ? "&allRemainingBookings=true" : ""
}`, }`,
icon: Icon.FiX, icon: FiX,
}, },
{ {
id: "edit_booking", id: "edit_booking",
@@ -143,13 +143,13 @@ function BookingListItem(booking: BookingItemProps) {
actions: [ actions: [
{ {
id: "reschedule", id: "reschedule",
icon: Icon.FiClock, icon: FiClock,
label: t("reschedule_booking"), label: t("reschedule_booking"),
href: `/reschedule/${booking.uid}`, href: `/reschedule/${booking.uid}`,
}, },
{ {
id: "reschedule_request", id: "reschedule_request",
icon: Icon.FiSend, icon: FiSend,
iconClassName: "rotate-45 w-[16px] -translate-x-0.5 ", iconClassName: "rotate-45 w-[16px] -translate-x-0.5 ",
label: t("send_reschedule_request"), label: t("send_reschedule_request"),
onClick: () => { onClick: () => {
@@ -162,7 +162,7 @@ function BookingListItem(booking: BookingItemProps) {
onClick: () => { onClick: () => {
setIsOpenLocationDialog(true); setIsOpenLocationDialog(true);
}, },
icon: Icon.FiMapPin, icon: FiMapPin,
}, },
], ],
}, },
@@ -179,7 +179,7 @@ function BookingListItem(booking: BookingItemProps) {
const RequestSentMessage = () => { const RequestSentMessage = () => {
return ( return (
<div className="ml-1 mr-8 flex text-gray-500" data-testid="request_reschedule_sent"> <div className="ml-1 mr-8 flex text-gray-500" data-testid="request_reschedule_sent">
<Icon.FiSend className="-mt-[1px] w-4 rotate-45" /> <FiSend className="-mt-[1px] w-4 rotate-45" />
<p className="ml-2 ">{t("reschedule_request_sent")}</p> <p className="ml-2 ">{t("reschedule_request_sent")}</p>
</div> </div>
); );
@@ -455,7 +455,7 @@ const RecurringBookingsTooltip = ({ booking, recurringDates }: RecurringBookings
); );
})}> })}>
<div className="text-gray-600 dark:text-white"> <div className="text-gray-600 dark:text-white">
<Icon.FiRefreshCcw <FiRefreshCcw
strokeWidth="3" strokeWidth="3"
className="float-left mr-1 mt-1.5 inline-block h-3 w-3 text-gray-400" className="float-left mr-1 mt-1.5 inline-block h-3 w-3 text-gray-400"
/> />
@@ -5,7 +5,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import useTheme from "@calcom/lib/hooks/useTheme"; import useTheme from "@calcom/lib/hooks/useTheme";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import type { RecurringEvent } from "@calcom/types/Calendar"; import type { RecurringEvent } from "@calcom/types/Calendar";
import { Button, Icon, TextArea } from "@calcom/ui"; import { Button, TextArea } from "@calcom/ui";
import { FiX } from "@calcom/ui/components/icon";
type Props = { type Props = {
booking: { booking: {
@@ -39,7 +40,7 @@ export default function CancelBooking(props: Props) {
{error && ( {error && (
<div className="mt-8"> <div className="mt-8">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
<Icon.FiX className="h-6 w-6 text-red-600" /> <FiX className="h-6 w-6 text-red-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title">
@@ -28,7 +28,8 @@ import { getRecurringFreq } from "@calcom/lib/recurringStrings";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { detectBrowserTimeFormat, setIs24hClockInLocalStorage, TimeFormat } from "@calcom/lib/timeFormat"; import { detectBrowserTimeFormat, setIs24hClockInLocalStorage, TimeFormat } from "@calcom/lib/timeFormat";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Icon, HeadSeo } from "@calcom/ui"; import { HeadSeo } from "@calcom/ui";
import { FiChevronDown, FiChevronUp, FiCreditCard, FiGlobe, FiRefreshCcw } from "@calcom/ui/components/icon";
import { timeZone as localStorageTimeZone } from "@lib/clock"; import { timeZone as localStorageTimeZone } from "@lib/clock";
import useRouterQuery from "@lib/hooks/useRouterQuery"; import useRouterQuery from "@lib/hooks/useRouterQuery";
@@ -220,12 +221,12 @@ function TimezoneDropdown({
<Popover.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}> <Popover.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}>
<Popover.Trigger className="min-w-32 dark:text-darkgray-600 radix-state-open:bg-gray-200 dark:radix-state-open:bg-darkgray-200 group relative mb-2 -ml-2 !mt-2 inline-block self-start rounded-md px-2 py-2 text-left text-gray-600"> <Popover.Trigger className="min-w-32 dark:text-darkgray-600 radix-state-open:bg-gray-200 dark:radix-state-open:bg-darkgray-200 group relative mb-2 -ml-2 !mt-2 inline-block self-start rounded-md px-2 py-2 text-left text-gray-600">
<p className="flex items-center text-sm font-medium"> <p className="flex items-center text-sm font-medium">
<Icon.FiGlobe className="min-h-4 min-w-4 ml-[2px] -mt-[2px] inline-block ltr:mr-[10px] rtl:ml-[10px]" /> <FiGlobe className="min-h-4 min-w-4 ml-[2px] -mt-[2px] inline-block ltr:mr-[10px] rtl:ml-[10px]" />
{timeZone} {timeZone}
{isTimeOptionsOpen ? ( {isTimeOptionsOpen ? (
<Icon.FiChevronUp className="min-h-4 min-w-4 ml-1 inline-block" /> <FiChevronUp className="min-h-4 min-w-4 ml-1 inline-block" />
) : ( ) : (
<Icon.FiChevronDown className="min-h-4 min-w-4 ml-1 inline-block" /> <FiChevronDown className="min-h-4 min-w-4 ml-1 inline-block" />
)} )}
</p> </p>
</Popover.Trigger> </Popover.Trigger>
@@ -367,7 +368,7 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
<BookingDescription profile={profile} eventType={eventType} rescheduleUid={rescheduleUid}> <BookingDescription profile={profile} eventType={eventType} rescheduleUid={rescheduleUid}>
{!rescheduleUid && eventType.recurringEvent && ( {!rescheduleUid && eventType.recurringEvent && (
<div className="flex items-start text-sm font-medium"> <div className="flex items-start text-sm font-medium">
<Icon.FiRefreshCcw className="float-left mt-[7px] ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px] " /> <FiRefreshCcw className="float-left mt-[7px] ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px] " />
<div> <div>
<p className="mb-1 -ml-2 inline px-2 py-1"> <p className="mb-1 -ml-2 inline px-2 py-1">
{getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })} {getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })}
@@ -392,7 +393,7 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
)} )}
{stripeAppData.price > 0 && ( {stripeAppData.price > 0 && (
<p className="-ml-2 px-2 text-sm font-medium"> <p className="-ml-2 px-2 text-sm font-medium">
<Icon.FiCreditCard className="ml-[2px] -mt-1 inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" /> <FiCreditCard className="ml-[2px] -mt-1 inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" />
<IntlProvider locale="en"> <IntlProvider locale="en">
<FormattedNumber <FormattedNumber
value={stripeAppData.price / 100.0} value={stripeAppData.price / 100.0}
@@ -39,8 +39,16 @@ import useTheme from "@calcom/lib/hooks/useTheme";
import { HttpError } from "@calcom/lib/http-error"; import { HttpError } from "@calcom/lib/http-error";
import { getEveryFreqFor } from "@calcom/lib/recurringStrings"; import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { AddressInput, Button, EmailInput, Form, Icon, PhoneInput, Tooltip } from "@calcom/ui"; import { AddressInput, Button, EmailInput, Form, PhoneInput, Tooltip, Group, RadioField } from "@calcom/ui";
import { Group, RadioField } from "@calcom/ui"; import {
FiAlertTriangle,
FiCalendar,
FiCreditCard,
FiInfo,
FiRefreshCw,
FiUser,
FiUserPlus,
} from "@calcom/ui/components/icon";
import { asStringOrNull } from "@lib/asStringOrNull"; import { asStringOrNull } from "@lib/asStringOrNull";
import { timeZone } from "@lib/clock"; import { timeZone } from "@lib/clock";
@@ -479,7 +487,7 @@ const BookingPage = ({
})}{" "} })}{" "}
| {APP_NAME} | {APP_NAME}
</title> </title>
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favico.ico" />
</Head> </Head>
<BookingPageTagManager eventType={eventType} /> <BookingPageTagManager eventType={eventType} />
<CustomBranding lightVal={profile.brandColor} darkVal={profile.darkBrandColor} /> <CustomBranding lightVal={profile.brandColor} darkVal={profile.darkBrandColor} />
@@ -501,7 +509,7 @@ const BookingPage = ({
<BookingDescription isBookingPage profile={profile} eventType={eventType}> <BookingDescription isBookingPage profile={profile} eventType={eventType}>
{stripeAppData.price > 0 && ( {stripeAppData.price > 0 && (
<p className="text-bookinglight -ml-2 px-2 text-sm "> <p className="text-bookinglight -ml-2 px-2 text-sm ">
<Icon.FiCreditCard className="ml-[2px] -mt-1 inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" /> <FiCreditCard className="ml-[2px] -mt-1 inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" />
<IntlProvider locale="en"> <IntlProvider locale="en">
<FormattedNumber <FormattedNumber
value={stripeAppData.price / 100.0} value={stripeAppData.price / 100.0}
@@ -513,7 +521,7 @@ const BookingPage = ({
)} )}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && ( {!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && (
<div className="items-start text-sm font-medium text-gray-600 dark:text-white"> <div className="items-start text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiRefreshCw className="ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" /> <FiRefreshCw className="ml-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" />
<p className="-ml-2 inline-block items-center px-2"> <p className="-ml-2 inline-block items-center px-2">
{getEveryFreqFor({ {getEveryFreqFor({
t, t,
@@ -524,7 +532,7 @@ const BookingPage = ({
</div> </div>
)} )}
<div className="text-bookinghighlight flex items-start text-sm"> <div className="text-bookinghighlight flex items-start text-sm">
<Icon.FiCalendar className="ml-[2px] mt-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" /> <FiCalendar className="ml-[2px] mt-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" />
<div className="text-sm font-medium"> <div className="text-sm font-medium">
{(rescheduleUid || !eventType.recurringEvent?.freq) && `${parseDate(date, i18n)}`} {(rescheduleUid || !eventType.recurringEvent?.freq) && `${parseDate(date, i18n)}`}
{!rescheduleUid && {!rescheduleUid &&
@@ -552,14 +560,14 @@ const BookingPage = ({
{t("former_time")} {t("former_time")}
</p> </p>
<p className="line-through "> <p className="line-through ">
<Icon.FiCalendar className="ml-[2px] -mt-1 inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" /> <FiCalendar className="ml-[2px] -mt-1 inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px]" />
{typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)} {typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)}
</p> </p>
</div> </div>
)} )}
{!!eventType.seatsPerTimeSlot && ( {!!eventType.seatsPerTimeSlot && (
<div className="text-bookinghighlight flex items-start text-sm"> <div className="text-bookinghighlight flex items-start text-sm">
<Icon.FiUser <FiUser
className={`ml-[2px] mt-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px] ${ className={`ml-[2px] mt-[2px] inline-block h-4 w-4 ltr:mr-[10px] rtl:ml-[10px] ${
booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.5 booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.5
? "text-rose-600" ? "text-rose-600"
@@ -623,7 +631,7 @@ const BookingPage = ({
/> />
{bookingForm.formState.errors.email && ( {bookingForm.formState.errors.email && (
<div className="mt-2 flex items-center text-sm text-red-700 "> <div className="mt-2 flex items-center text-sm text-red-700 ">
<Icon.FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" /> <FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" />
<p>{t("email_validation_error")}</p> <p>{t("email_validation_error")}</p>
</div> </div>
)} )}
@@ -716,7 +724,7 @@ const BookingPage = ({
</div> </div>
{bookingForm.formState.errors.phone && ( {bookingForm.formState.errors.phone && (
<div className="mt-2 flex items-center text-sm text-red-700 "> <div className="mt-2 flex items-center text-sm text-red-700 ">
<Icon.FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" /> <FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" />
<p>{t("invalid_number")}</p> <p>{t("invalid_number")}</p>
</div> </div>
)} )}
@@ -834,7 +842,7 @@ const BookingPage = ({
/> />
{bookingForm.formState.errors?.customInputs?.[input.id] && ( {bookingForm.formState.errors?.customInputs?.[input.id] && (
<div className="mt-2 flex items-center text-sm text-red-700 "> <div className="mt-2 flex items-center text-sm text-red-700 ">
<Icon.FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" /> <FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" />
<p>{t("invalid_number")}</p> <p>{t("invalid_number")}</p>
</div> </div>
)} )}
@@ -914,7 +922,7 @@ const BookingPage = ({
</div> </div>
{bookingForm.formState.errors.smsReminderNumber && ( {bookingForm.formState.errors.smsReminderNumber && (
<div className="mt-2 flex items-center text-sm text-red-700 "> <div className="mt-2 flex items-center text-sm text-red-700 ">
<Icon.FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" /> <FiInfo className="h-3 w-3 ltr:mr-2 rtl:ml-2" />
<p>{t("invalid_number")}</p> <p>{t("invalid_number")}</p>
</div> </div>
)} )}
@@ -956,7 +964,7 @@ const BookingPage = ({
color="minimal" color="minimal"
variant="icon" variant="icon"
tooltip={t("additional_guests")} tooltip={t("additional_guests")}
StartIcon={Icon.FiUserPlus} StartIcon={FiUserPlus}
onClick={() => setGuestToggle(!guestToggle)} onClick={() => setGuestToggle(!guestToggle)}
className="mr-auto" className="mr-auto"
/> />
@@ -993,7 +1001,7 @@ function ErrorMessage({ error }: { error: unknown }) {
<div data-testid="booking-fail" className="mt-2 border-l-4 border-yellow-400 bg-yellow-50 p-4"> <div data-testid="booking-fail" className="mt-2 border-l-4 border-yellow-400 bg-yellow-50 p-4">
<div className="flex"> <div className="flex">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<Icon.FiAlertTriangle className="h-5 w-5 text-yellow-400" aria-hidden="true" /> <FiAlertTriangle className="h-5 w-5 text-yellow-400" aria-hidden="true" />
</div> </div>
<div className="ltr:ml-3 rtl:mr-3"> <div className="ltr:ml-3 rtl:mr-3">
<p className="text-sm text-yellow-700"> <p className="text-sm text-yellow-700">
@@ -15,7 +15,8 @@ import {
} from "@calcom/app-store/locations"; } from "@calcom/app-store/locations";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { RouterOutputs, trpc } from "@calcom/trpc/react";
import { Button, Dialog, DialogContent, DialogFooter, Form, Icon, PhoneInput } from "@calcom/ui"; import { Button, Dialog, DialogContent, DialogFooter, Form, PhoneInput } from "@calcom/ui";
import { FiMapPin } from "@calcom/ui/components/icon";
import { QueryCell } from "@lib/QueryCell"; import { QueryCell } from "@lib/QueryCell";
@@ -204,10 +205,10 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
return ( return (
<Dialog open={isOpenDialog} onOpenChange={(open) => setShowLocationModal(open)}> <Dialog open={isOpenDialog} onOpenChange={(open) => setShowLocationModal(open)}>
<DialogContent disableOverflow> <DialogContent>
<div className="flex flex-row space-x-3"> <div className="flex flex-row space-x-3">
<div className="bg-secondary-100 mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full sm:mx-0 sm:h-10 sm:w-10"> <div className="bg-secondary-100 mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full sm:mx-0 sm:h-10 sm:w-10">
<Icon.FiMapPin className="text-primary-600 h-6 w-6" /> <FiMapPin className="text-primary-600 h-6 w-6" />
</div> </div>
<div className="w-full"> <div className="w-full">
<div className="mt-3 text-center sm:mt-0 sm:text-left"> <div className="mt-3 text-center sm:mt-0 sm:text-left">
@@ -288,30 +289,31 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
name="locationType" name="locationType"
control={locationFormMethods.control} control={locationFormMethods.control}
render={() => ( render={() => (
<LocationSelect <div className="py-4">
maxMenuHeight={300} <LocationSelect
name="location" maxMenuHeight={300}
defaultValue={selection} name="location"
options={locationOptions} defaultValue={selection}
isSearchable options={locationOptions}
className="my-4 block w-full min-w-0 flex-1 rounded-sm border border-gray-300 text-sm" isSearchable
onChange={(val) => { onChange={(val) => {
if (val) { if (val) {
locationFormMethods.setValue("locationType", val.value); locationFormMethods.setValue("locationType", val.value);
locationFormMethods.unregister([ locationFormMethods.unregister([
"locationLink", "locationLink",
"locationAddress", "locationAddress",
"locationPhoneNumber", "locationPhoneNumber",
]); ]);
locationFormMethods.clearErrors([ locationFormMethods.clearErrors([
"locationLink", "locationLink",
"locationPhoneNumber", "locationPhoneNumber",
"locationAddress", "locationAddress",
]); ]);
setSelectedLocation?.(val); setSelectedLocation?.(val);
} }
}} }}
/> />
</div>
)} )}
/> />
); );
@@ -9,10 +9,10 @@ import {
DialogContent, DialogContent,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
Icon,
showToast, showToast,
TextArea, TextArea,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiClock } from "@calcom/ui/components/icon";
interface IRescheduleDialog { interface IRescheduleDialog {
isOpenDialog: boolean; isOpenDialog: boolean;
@@ -43,7 +43,7 @@ export const RescheduleDialog = (props: IRescheduleDialog) => {
<DialogContent> <DialogContent>
<div className="flex flex-row space-x-3"> <div className="flex flex-row space-x-3">
<div className="flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]"> <div className="flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]">
<Icon.FiClock className="m-auto h-6 w-6" /> <FiClock className="m-auto h-6 w-6" />
</div> </div>
<div className="pt-1"> <div className="pt-1">
<DialogHeader title={t("send_reschedule_request")} /> <DialogHeader title={t("send_reschedule_request")} />
@@ -8,7 +8,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { weekdayNames } from "@calcom/lib/weekday"; import { weekdayNames } from "@calcom/lib/weekday";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery"; import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
import { Badge, Button, Icon, Select, SettingsToggle, SkeletonText } from "@calcom/ui"; import { Badge, Button, Select, SettingsToggle, SkeletonText } from "@calcom/ui";
import { FiExternalLink, FiGlobe } from "@calcom/ui/components/icon";
import { SelectSkeletonLoader } from "@components/availability/SkeletonLoader"; import { SelectSkeletonLoader } from "@components/availability/SkeletonLoader";
@@ -164,13 +165,13 @@ export const AvailabilityTab = ({ isTeamEvent }: { isTeamEvent: boolean }) => {
<hr /> <hr />
<div className="flex flex-col justify-center gap-2 sm:flex-row sm:justify-between"> <div className="flex flex-col justify-center gap-2 sm:flex-row sm:justify-between">
<span className="flex items-center justify-center text-sm text-gray-600 sm:justify-start"> <span className="flex items-center justify-center text-sm text-gray-600 sm:justify-start">
<Icon.FiGlobe className="ltr:mr-2 rtl:ml-2" /> <FiGlobe className="ltr:mr-2 rtl:ml-2" />
{schedule?.timeZone || <SkeletonText className="block h-5 w-32" />} {schedule?.timeZone || <SkeletonText className="block h-5 w-32" />}
</span> </span>
<Button <Button
href={`/availability/${schedule?.schedule.id}`} href={`/availability/${schedule?.schedule.id}`}
color="minimal" color="minimal"
EndIcon={Icon.FiExternalLink} EndIcon={FiExternalLink}
target="_blank" target="_blank"
className="justify-center border sm:border-0" className="justify-center border sm:border-0"
rel="noopener noreferrer"> rel="noopener noreferrer">
@@ -5,7 +5,8 @@ import { FC } from "react";
import { Control, Controller, useFieldArray, useForm, UseFormRegister, useWatch } from "react-hook-form"; import { Control, Controller, useFieldArray, useForm, UseFormRegister, useWatch } from "react-hook-form";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, Label, Select, TextField } from "@calcom/ui"; import { Button, Label, Select, TextField } from "@calcom/ui";
import { FiPlus, FiX } from "@calcom/ui/components/icon";
interface OptionTypeBase { interface OptionTypeBase {
label: string; label: string;
@@ -77,7 +78,7 @@ const CustomInputTypeForm: FC<Props> = (props) => {
defaultValue={selectedInputOption} defaultValue={selectedInputOption}
options={inputOptions} options={inputOptions}
isSearchable={false} isSearchable={false}
className="mt-1 mb-2 block w-full min-w-0 flex-1 text-sm" className="mt-1 mb-2 block w-full min-w-0 flex-1 text-sm"
onChange={(option) => option && field.onChange(option.value)} onChange={(option) => option && field.onChange(option.value)}
value={selectedInputOption} value={selectedInputOption}
onBlur={field.onBlur} onBlur={field.onBlur}
@@ -185,7 +186,7 @@ function RadioInputHandler({
<Button <Button
variant="icon" variant="icon"
color="minimal" color="minimal"
StartIcon={Icon.FiX} StartIcon={FiX}
onClick={() => { onClick={() => {
remove(index); remove(index);
}} }}
@@ -196,7 +197,7 @@ function RadioInputHandler({
))} ))}
<Button <Button
color="minimal" color="minimal"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
className="!text-sm !font-medium" className="!text-sm !font-medium"
onClick={() => { onClick={() => {
append({ label: "", type: "text" }); append({ label: "", type: "text" });
@@ -18,13 +18,13 @@ import {
DialogClose, DialogClose,
DialogContent, DialogContent,
DialogFooter, DialogFooter,
Icon,
Label, Label,
SettingsToggle, SettingsToggle,
showToast, showToast,
TextField, TextField,
Tooltip, Tooltip,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiEdit, FiCopy, FiPlus } from "@calcom/ui/components/icon";
import CustomInputTypeForm from "@components/eventtype/CustomInputTypeForm"; import CustomInputTypeForm from "@components/eventtype/CustomInputTypeForm";
@@ -128,7 +128,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
addOnSuffix={ addOnSuffix={
<Button <Button
type="button" type="button"
StartIcon={Icon.FiEdit} StartIcon={FiEdit}
variant="icon" variant="icon"
color="minimal" color="minimal"
className="hover:stroke-3 min-w-fit px-0 hover:bg-transparent hover:text-black" className="hover:stroke-3 min-w-fit px-0 hover:bg-transparent hover:text-black"
@@ -168,7 +168,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
</ul> </ul>
{customInputs.length > 0 && ( {customInputs.length > 0 && (
<Button <Button
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
color="minimal" color="minimal"
type="button" type="button"
onClick={() => { onClick={() => {
@@ -314,7 +314,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
}} }}
className="hover:stroke-3 hover:bg-transparent hover:text-black" className="hover:stroke-3 hover:bg-transparent hover:text-black"
type="button"> type="button">
<Icon.FiCopy /> <FiCopy />
</Button> </Button>
</Tooltip> </Tooltip>
} }
@@ -413,7 +413,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
<Dialog open={selectedCustomInputModalOpen} onOpenChange={setSelectedCustomInputModalOpen}> <Dialog open={selectedCustomInputModalOpen} onOpenChange={setSelectedCustomInputModalOpen}>
<DialogContent <DialogContent
type="creation" type="creation"
Icon={Icon.FiPlus} Icon={FiPlus}
title={t("add_new_custom_input_field")} title={t("add_new_custom_input_field")}
description={t("this_input_will_shown_booking_this_event")}> description={t("this_input_will_shown_booking_this_event")}>
<CustomInputTypeForm <CustomInputTypeForm
@@ -7,7 +7,8 @@ import { EventTypeAppCardComponentProps } from "@calcom/app-store/types";
import { EventTypeAppsList } from "@calcom/app-store/utils"; import { EventTypeAppsList } from "@calcom/app-store/utils";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, EmptyScreen, Icon } from "@calcom/ui"; import { Button, EmptyScreen } from "@calcom/ui";
import { FiGrid } from "@calcom/ui/components/icon";
export type EventType = Pick<EventTypeSetupProps, "eventType">["eventType"] & export type EventType = Pick<EventTypeSetupProps, "eventType">["eventType"] &
EventTypeAppCardComponentProps["eventType"]; EventTypeAppCardComponentProps["eventType"];
@@ -60,7 +61,7 @@ export const EventAppsTab = ({ eventType }: { eventType: EventType }) => {
<div className="before:border-0"> <div className="before:border-0">
{!isLoading && !installedApps?.length ? ( {!isLoading && !installedApps?.length ? (
<EmptyScreen <EmptyScreen
Icon={Icon.FiGrid} Icon={FiGrid}
headline={t("empty_installed_apps_headline")} headline={t("empty_installed_apps_headline")}
description={t("empty_installed_apps_description")} description={t("empty_installed_apps_description")}
buttonRaw={ buttonRaw={
@@ -10,7 +10,8 @@ import findDurationType from "@calcom/lib/findDurationType";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { PeriodType } from "@calcom/prisma/client"; import { PeriodType } from "@calcom/prisma/client";
import type { BookingLimit } from "@calcom/types/Calendar"; import type { BookingLimit } from "@calcom/types/Calendar";
import { Button, DateRangePicker, Icon, Input, InputField, Label, Select, SettingsToggle } from "@calcom/ui"; import { Button, DateRangePicker, Input, InputField, Label, Select, SettingsToggle } from "@calcom/ui";
import { FiPlus, FiTrash } from "@calcom/ui/components/icon";
const MinimumBookingNoticeInput = React.forwardRef< const MinimumBookingNoticeInput = React.forwardRef<
HTMLInputElement, HTMLInputElement,
@@ -431,7 +432,7 @@ const BookingLimits = () => {
/> />
<Button <Button
variant="icon" variant="icon"
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
color="destructive" color="destructive"
onClick={() => { onClick={() => {
const current = currentBookingLimits; const current = currentBookingLimits;
@@ -445,7 +446,7 @@ const BookingLimits = () => {
{currentBookingLimits && Object.keys(currentBookingLimits).length <= 3 && ( {currentBookingLimits && Object.keys(currentBookingLimits).length <= 3 && (
<Button <Button
color="minimal" color="minimal"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
onClick={() => { onClick={() => {
if (!currentBookingLimits || !watchBookingLimits) return; if (!currentBookingLimits || !watchBookingLimits) return;
const currentKeys = Object.keys(watchBookingLimits); const currentKeys = Object.keys(watchBookingLimits);
@@ -12,7 +12,8 @@ import { z } from "zod";
import { EventLocationType, getEventLocationType, MeetLocationType } from "@calcom/app-store/locations"; import { EventLocationType, getEventLocationType, MeetLocationType } from "@calcom/app-store/locations";
import { CAL_URL } from "@calcom/lib/constants"; import { CAL_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, Label, Select, SettingsToggle, Skeleton, TextField } from "@calcom/ui"; import { Button, Label, Select, SettingsToggle, Skeleton, TextField } from "@calcom/ui";
import { FiEdit2, FiCheck, FiX, FiPlus } from "@calcom/ui/components/icon";
import { slugify } from "@lib/slugify"; import { slugify } from "@lib/slugify";
@@ -138,11 +139,13 @@ export const EventSetupTab = (
return true; return true;
}); });
const defaultValue = locationOptions.find((item) => item.label === "video")?.options;
return ( return (
<div className="w-full"> <div className="w-full">
{validLocations.length === 0 && ( {validLocations.length === 0 && (
<div className="flex"> <div className="flex">
<LocationSelect <LocationSelect
defaultValue={defaultValue}
placeholder={t("select")} placeholder={t("select")}
options={locationOptions} options={locationOptions}
isSearchable={false} isSearchable={false}
@@ -198,10 +201,10 @@ export const EventSetupTab = (
}} }}
aria-label={t("edit")} aria-label={t("edit")}
className="mr-1 p-1 text-gray-500 hover:text-gray-900"> className="mr-1 p-1 text-gray-500 hover:text-gray-900">
<Icon.FiEdit2 className="h-4 w-4" /> <FiEdit2 className="h-4 w-4" />
</button> </button>
<button type="button" onClick={() => removeLocation(location)} aria-label={t("remove")}> <button type="button" onClick={() => removeLocation(location)} aria-label={t("remove")}>
<Icon.FiX className="border-l-1 h-6 w-6 pl-1 text-gray-500 hover:text-gray-900 " /> <FiX className="border-l-1 h-6 w-6 pl-1 text-gray-500 hover:text-gray-900 " />
</button> </button>
</div> </div>
</div> </div>
@@ -210,7 +213,7 @@ export const EventSetupTab = (
})} })}
{validLocations.some((location) => location.type === MeetLocationType) && ( {validLocations.some((location) => location.type === MeetLocationType) && (
<div className="flex text-sm text-gray-600"> <div className="flex text-sm text-gray-600">
<Icon.FiCheck className="mt-0.5 mr-1.5 h-2 w-2.5" /> <FiCheck className="mt-0.5 mr-1.5 h-2 w-2.5" />
<Trans i18nKey="event_type_requres_google_cal"> <Trans i18nKey="event_type_requres_google_cal">
<p> <p>
The “Add to calendar” for this event type needs to be a Google Calendar for Meet to work. The “Add to calendar” for this event type needs to be a Google Calendar for Meet to work.
@@ -227,7 +230,7 @@ export const EventSetupTab = (
)} )}
{validLocations.length > 0 && validLocations.length !== locationOptions.length && ( {validLocations.length > 0 && validLocations.length !== locationOptions.length && (
<li> <li>
<Button StartIcon={Icon.FiPlus} color="minimal" onClick={() => setShowLocationModal(true)}> <Button StartIcon={FiPlus} color="minimal" onClick={() => setShowLocationModal(true)}>
{t("add_location")} {t("add_location")}
</Button> </Button>
</li> </li>
@@ -9,7 +9,8 @@ import { APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Webhook } from "@calcom/prisma/client"; import { Webhook } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, Dialog, DialogContent, EmptyScreen, Icon, showToast } from "@calcom/ui"; import { Button, Dialog, DialogContent, EmptyScreen, showToast } from "@calcom/ui";
import { FiPlus } from "@calcom/ui/components/icon";
export const EventTeamWebhooksTab = ({ export const EventTeamWebhooksTab = ({
eventType, eventType,
@@ -84,7 +85,7 @@ export const EventTeamWebhooksTab = ({
<Button <Button
color="secondary" color="secondary"
data-testid="new_webhook" data-testid="new_webhook"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
onClick={() => setCreateModalOpen(true)}> onClick={() => setCreateModalOpen(true)}>
{t("new_webhook")} {t("new_webhook")}
</Button> </Button>
@@ -130,7 +131,10 @@ export const EventTeamWebhooksTab = ({
{/* New webhook dialog */} {/* New webhook dialog */}
<Dialog open={createModalOpen} onOpenChange={(isOpen) => !isOpen && setCreateModalOpen(false)}> <Dialog open={createModalOpen} onOpenChange={(isOpen) => !isOpen && setCreateModalOpen(false)}>
<DialogContent title={t("create_webhook")} description={t("create_webhook_team_event_type")}> <DialogContent
enableOverflow
title={t("create_webhook")}
description={t("create_webhook_team_event_type")}>
<WebhookForm <WebhookForm
onSubmit={onCreateWebhook} onSubmit={onCreateWebhook}
onCancel={() => setCreateModalOpen(false)} onCancel={() => setCreateModalOpen(false)}
@@ -23,7 +23,6 @@ import {
DropdownItem, DropdownItem,
DropdownMenuTrigger, DropdownMenuTrigger,
HorizontalTabs, HorizontalTabs,
Icon,
Label, Label,
showToast, showToast,
Skeleton, Skeleton,
@@ -32,6 +31,21 @@ import {
VerticalDivider, VerticalDivider,
VerticalTabs, VerticalTabs,
} from "@calcom/ui"; } from "@calcom/ui";
import {
FiLink,
FiCalendar,
FiClock,
FiSliders,
FiRepeat,
FiGrid,
FiZap,
FiUsers,
FiExternalLink,
FiCode,
FiTrash,
FiMoreHorizontal,
FiLoader,
} from "@calcom/ui/components/icon";
import { EmbedButton, EmbedDialog } from "@components/Embed"; import { EmbedButton, EmbedDialog } from "@components/Embed";
@@ -63,44 +77,44 @@ function getNavigation(props: {
{ {
name: "event_setup_tab_title", name: "event_setup_tab_title",
href: `/event-types/${eventType.id}?tabName=setup`, href: `/event-types/${eventType.id}?tabName=setup`,
icon: Icon.FiLink, icon: FiLink,
info: `${duration} ${t("minute_timeUnit")}`, // TODO: Get this from props info: `${duration} ${t("minute_timeUnit")}`, // TODO: Get this from props
}, },
{ {
name: "availability", name: "availability",
href: `/event-types/${eventType.id}?tabName=availability`, href: `/event-types/${eventType.id}?tabName=availability`,
icon: Icon.FiCalendar, icon: FiCalendar,
info: `default_schedule_name`, // TODO: Get this from props info: `default_schedule_name`, // TODO: Get this from props
}, },
{ {
name: "event_limit_tab_title", name: "event_limit_tab_title",
href: `/event-types/${eventType.id}?tabName=limits`, href: `/event-types/${eventType.id}?tabName=limits`,
icon: Icon.FiClock, icon: FiClock,
info: `event_limit_tab_description`, info: `event_limit_tab_description`,
}, },
{ {
name: "event_advanced_tab_title", name: "event_advanced_tab_title",
href: `/event-types/${eventType.id}?tabName=advanced`, href: `/event-types/${eventType.id}?tabName=advanced`,
icon: Icon.FiSliders, icon: FiSliders,
info: `event_advanced_tab_description`, info: `event_advanced_tab_description`,
}, },
{ {
name: "recurring", name: "recurring",
href: `/event-types/${eventType.id}?tabName=recurring`, href: `/event-types/${eventType.id}?tabName=recurring`,
icon: Icon.FiRepeat, icon: FiRepeat,
info: `recurring_event_tab_description`, info: `recurring_event_tab_description`,
}, },
{ {
name: "apps", name: "apps",
href: `/event-types/${eventType.id}?tabName=apps`, href: `/event-types/${eventType.id}?tabName=apps`,
icon: Icon.FiGrid, icon: FiGrid,
//TODO: Handle proper translation with count handling //TODO: Handle proper translation with count handling
info: `${installedAppsNumber} apps, ${enabledAppsNumber} ${t("active")}`, info: `${installedAppsNumber} apps, ${enabledAppsNumber} ${t("active")}`,
}, },
{ {
name: "workflows", name: "workflows",
href: `/event-types/${eventType.id}?tabName=workflows`, href: `/event-types/${eventType.id}?tabName=workflows`,
icon: Icon.FiZap, icon: FiZap,
info: `${enabledWorkflowsNumber} ${t("active")}`, info: `${enabledWorkflowsNumber} ${t("active")}`,
}, },
]; ];
@@ -157,7 +171,7 @@ function EventTypeSingleLayout({
navigation.splice(2, 0, { navigation.splice(2, 0, {
name: "assignment", name: "assignment",
href: `/event-types/${eventType.id}?tabName=team`, href: `/event-types/${eventType.id}?tabName=team`,
icon: Icon.FiUsers, icon: FiUsers,
info: eventType.schedulingType === "COLLECTIVE" ? "collective" : "round_robin", info: eventType.schedulingType === "COLLECTIVE" ? "collective" : "round_robin",
}); });
navigation.push({ navigation.push({
@@ -211,14 +225,14 @@ function EventTypeSingleLayout({
variant="icon" variant="icon"
href={permalink} href={permalink}
rel="noreferrer" rel="noreferrer"
StartIcon={Icon.FiExternalLink} StartIcon={FiExternalLink}
/> />
</Tooltip> </Tooltip>
<Button <Button
color="secondary" color="secondary"
variant="icon" variant="icon"
StartIcon={Icon.FiLink} StartIcon={FiLink}
tooltip={t("copy_link")} tooltip={t("copy_link")}
onClick={() => { onClick={() => {
navigator.clipboard.writeText(permalink); navigator.clipboard.writeText(permalink);
@@ -227,7 +241,7 @@ function EventTypeSingleLayout({
/> />
<EmbedButton <EmbedButton
embedUrl={encodeURIComponent(embedLink)} embedUrl={encodeURIComponent(embedLink)}
StartIcon={Icon.FiCode} StartIcon={FiCode}
color="secondary" color="secondary"
variant="icon" variant="icon"
tooltip={t("embed")} tooltip={t("embed")}
@@ -235,7 +249,7 @@ function EventTypeSingleLayout({
<Button <Button
color="secondary" color="secondary"
variant="icon" variant="icon"
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
tooltip={t("delete")} tooltip={t("delete")}
disabled={!hasPermsToDelete} disabled={!hasPermsToDelete}
onClick={() => setDeleteDialogOpen(true)} onClick={() => setDeleteDialogOpen(true)}
@@ -246,19 +260,14 @@ function EventTypeSingleLayout({
<Dropdown> <Dropdown>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button <Button className="lg:hidden" StartIcon={FiMoreHorizontal} variant="icon" color="secondary" />
className="lg:hidden"
StartIcon={Icon.FiMoreHorizontal}
variant="icon"
color="secondary"
/>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
<DropdownMenuItem className="focus:ring-gray-100"> <DropdownMenuItem className="focus:ring-gray-100">
<DropdownItem <DropdownItem
target="_blank" target="_blank"
type="button" type="button"
StartIcon={Icon.FiExternalLink} StartIcon={FiExternalLink}
href={permalink} href={permalink}
rel="noreferrer"> rel="noreferrer">
{t("preview")} {t("preview")}
@@ -267,7 +276,7 @@ function EventTypeSingleLayout({
<DropdownMenuItem className="focus:ring-gray-100"> <DropdownMenuItem className="focus:ring-gray-100">
<DropdownItem <DropdownItem
type="button" type="button"
StartIcon={Icon.FiLink} StartIcon={FiLink}
onClick={() => { onClick={() => {
navigator.clipboard.writeText(permalink); navigator.clipboard.writeText(permalink);
showToast("Link copied!", "success"); showToast("Link copied!", "success");
@@ -278,7 +287,7 @@ function EventTypeSingleLayout({
<DropdownMenuItem className="focus:ring-gray-100"> <DropdownMenuItem className="focus:ring-gray-100">
<DropdownItem <DropdownItem
type="button" type="button"
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
disabled={!hasPermsToDelete} disabled={!hasPermsToDelete}
onClick={() => setDeleteDialogOpen(true)}> onClick={() => setDeleteDialogOpen(true)}>
{t("delete")} {t("delete")}
@@ -313,7 +322,7 @@ function EventTypeSingleLayout({
</Button> </Button>
</div> </div>
}> }>
<Suspense fallback={<Icon.FiLoader />}> <Suspense fallback={<FiLoader />}>
<div className="-mt-2 flex flex-col xl:flex-row xl:space-x-8"> <div className="-mt-2 flex flex-col xl:flex-row xl:space-x-8">
<div className="hidden xl:block"> <div className="hidden xl:block">
<VerticalTabs <VerticalTabs
@@ -1,4 +1,5 @@
import { Icon, SkeletonAvatar, SkeletonContainer, SkeletonText } from "@calcom/ui"; import { SkeletonAvatar, SkeletonContainer, SkeletonText } from "@calcom/ui";
import { FiClock, FiUser } from "@calcom/ui/components/icon";
function SkeletonLoader() { function SkeletonLoader() {
return ( return (
@@ -31,11 +32,11 @@ function SkeletonItem() {
<div className=""> <div className="">
<ul className="mt-2 flex space-x-4 rtl:space-x-reverse "> <ul className="mt-2 flex space-x-4 rtl:space-x-reverse ">
<li className="flex items-center whitespace-nowrap"> <li className="flex items-center whitespace-nowrap">
<Icon.FiClock className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200" /> <FiClock className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200" />
<SkeletonText className="h-4 w-12" /> <SkeletonText className="h-4 w-12" />
</li> </li>
<li className="flex items-center whitespace-nowrap"> <li className="flex items-center whitespace-nowrap">
<Icon.FiUser className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200" /> <FiUser className="mt-0.5 mr-1.5 inline h-4 w-4 text-gray-200" />
<SkeletonText className="h-4 w-12" /> <SkeletonText className="h-4 w-12" />
</li> </li>
</ul> </ul>
@@ -1,10 +1,10 @@
import { Icon } from "@calcom/ui"; import { ShieldCheckIcon } from "@calcom/ui/components/icon";
const TwoFactorModalHeader = ({ title, description }: { title: string; description: string }) => { const TwoFactorModalHeader = ({ title, description }: { title: string; description: string }) => {
return ( return (
<div className="mb-4 sm:flex sm:items-start"> <div className="mb-4 sm:flex sm:items-start">
<div className="bg-brand text-brandcontrast dark:bg-darkmodebrand dark:text-darkmodebrandcontrast mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-opacity-5 sm:mx-0 sm:h-10 sm:w-10"> <div className="bg-brand text-brandcontrast dark:bg-darkmodebrand dark:text-darkmodebrandcontrast mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-opacity-5 sm:mx-0 sm:h-10 sm:w-10">
<Icon.ShieldCheckIcon className="h-6 w-6 text-white" /> <ShieldCheckIcon className="h-6 w-6 text-white" />
</div> </div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 className="font-cal text-lg font-medium leading-6 text-gray-900" id="modal-title"> <h3 className="font-cal text-lg font-medium leading-6 text-gray-900" id="modal-title">
@@ -2,7 +2,8 @@ import { useMutation } from "@tanstack/react-query";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Badge, Icon, showToast, Switch } from "@calcom/ui"; import { Badge, showToast, Switch } from "@calcom/ui";
import { FiArrowLeft } from "@calcom/ui/components/icon";
export function CalendarSwitch(props: { export function CalendarSwitch(props: {
type: string; type: string;
@@ -74,7 +75,7 @@ export function CalendarSwitch(props: {
/> />
{props.defaultSelected && ( {props.defaultSelected && (
<Badge variant="gray"> <Badge variant="gray">
<Icon.FiArrowLeft className="mr-1" /> {t("adding_events_to")} <FiArrowLeft className="mr-1" /> {t("adding_events_to")}
</Badge> </Badge>
)} )}
</div> </div>
+3 -3
View File
@@ -1,8 +1,8 @@
import classNames from "classnames"; import classNames from "classnames";
import React, { useState } from "react"; import { useState } from "react";
import { ControllerRenderProps } from "react-hook-form"; import { ControllerRenderProps } from "react-hook-form";
import { Icon } from "@calcom/ui"; import { FiEdit2 } from "@calcom/ui/components/icon";
const EditableHeading = function EditableHeading({ const EditableHeading = function EditableHeading({
value, value,
@@ -21,7 +21,7 @@ const EditableHeading = function EditableHeading({
<label className="min-w-8 relative inline-block"> <label className="min-w-8 relative inline-block">
<span className="whitespace-pre text-xl tracking-normal text-transparent">{value}&nbsp;</span> <span className="whitespace-pre text-xl tracking-normal text-transparent">{value}&nbsp;</span>
{!isEditing && isReady && ( {!isEditing && isReady && (
<Icon.FiEdit2 className="ml-1 inline h-4 w-4 align-top text-gray-700 group-hover:text-gray-500" /> <FiEdit2 className="ml-1 inline h-4 w-4 align-top text-gray-700 group-hover:text-gray-500" />
)} )}
<input <input
{...passThroughProps} {...passThroughProps}
+3 -2
View File
@@ -1,11 +1,12 @@
import { Icon, Tooltip } from "@calcom/ui"; import { Tooltip } from "@calcom/ui";
import { FiInfo } from "@calcom/ui/components/icon";
export default function InfoBadge({ content }: { content: string }) { export default function InfoBadge({ content }: { content: string }) {
return ( return (
<> <>
<Tooltip side="top" content={content}> <Tooltip side="top" content={content}>
<span title={content}> <span title={content}>
<Icon.FiInfo className="relative top-px left-1 right-1 mt-px h-4 w-4 text-gray-500" /> <FiInfo className="relative top-px left-1 right-1 mt-px h-4 w-4 text-gray-500" />
</span> </span>
</Tooltip> </Tooltip>
</> </>
@@ -11,7 +11,8 @@ import { User } from "@calcom/prisma/client";
import { TRPCClientErrorLike } from "@calcom/trpc/client"; import { TRPCClientErrorLike } from "@calcom/trpc/client";
import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { RouterOutputs, trpc } from "@calcom/trpc/react";
import type { AppRouter } from "@calcom/trpc/server/routers/_app"; import type { AppRouter } from "@calcom/trpc/server/routers/_app";
import { Button, Dialog, DialogClose, DialogContent, DialogHeader, Icon, Input, Label } from "@calcom/ui"; import { Button, Dialog, DialogClose, DialogContent, DialogHeader, Input, Label } from "@calcom/ui";
import { FiCheck, FiEdit2, FiExternalLink, StarIconSolid } from "@calcom/ui/components/icon";
export enum UsernameChangeStatusEnum { export enum UsernameChangeStatusEnum {
UPGRADE = "UPGRADE", UPGRADE = "UPGRADE",
@@ -230,8 +231,8 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
isInputUsernamePremium ? "text-orange-400" : "", isInputUsernamePremium ? "text-orange-400" : "",
usernameIsAvailable ? "" : "" usernameIsAvailable ? "" : ""
)}> )}>
{isInputUsernamePremium ? <Icon.StarIconSolid className="mt-[2px] w-6" /> : <></>} {isInputUsernamePremium ? <StarIconSolid className="mt-[2px] w-6" /> : <></>}
{!isInputUsernamePremium && usernameIsAvailable ? <Icon.FiCheck className="mt-2 w-6" /> : <></>} {!isInputUsernamePremium && usernameIsAvailable ? <FiCheck className="mt-2 w-6" /> : <></>}
</span> </span>
</div> </div>
</div> </div>
@@ -249,7 +250,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
<DialogContent> <DialogContent>
<div className="flex flex-row"> <div className="flex flex-row">
<div className="xs:hidden flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]"> <div className="xs:hidden flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]">
<Icon.FiEdit2 className="m-auto h-6 w-6" /> <FiEdit2 className="m-auto h-6 w-6" />
</div> </div>
<div className="mb-4 w-full px-4 pt-1"> <div className="mb-4 w-full px-4 pt-1">
<DialogHeader title={t("confirm_username_change_dialog_title")} /> <DialogHeader title={t("confirm_username_change_dialog_title")} />
@@ -283,7 +284,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
data-testid="go-to-billing" data-testid="go-to-billing"
href={paymentLink}> href={paymentLink}>
<> <>
{t("go_to_stripe_billing")} <Icon.FiExternalLink className="ml-1 h-4 w-4" /> {t("go_to_stripe_billing")} <FiExternalLink className="ml-1 h-4 w-4" />
</> </>
</Button> </Button>
)} )}
@@ -7,17 +7,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { TRPCClientErrorLike } from "@calcom/trpc/client"; import { TRPCClientErrorLike } from "@calcom/trpc/client";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { AppRouter } from "@calcom/trpc/server/routers/_app"; import { AppRouter } from "@calcom/trpc/server/routers/_app";
import { import { Button, Dialog, DialogClose, DialogContent, DialogHeader, TextField } from "@calcom/ui";
Button, import { FiCheck, FiEdit2 } from "@calcom/ui/components/icon";
Dialog,
DialogClose,
DialogContent,
DialogHeader,
Icon,
Input,
Label,
TextField,
} from "@calcom/ui";
interface ICustomUsernameProps { interface ICustomUsernameProps {
currentUsername: string | undefined; currentUsername: string | undefined;
@@ -145,7 +136,7 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
{currentUsername !== inputUsernameValue && ( {currentUsername !== inputUsernameValue && (
<div className="absolute right-[2px] top-6 flex flex-row"> <div className="absolute right-[2px] top-6 flex flex-row">
<span className={classNames("mx-2 py-2")}> <span className={classNames("mx-2 py-2")}>
{usernameIsAvailable ? <Icon.FiCheck className="w-6" /> : <></>} {usernameIsAvailable ? <FiCheck className="w-6" /> : <></>}
</span> </span>
</div> </div>
)} )}
@@ -165,7 +156,7 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
<DialogContent> <DialogContent>
<div style={{ display: "flex", flexDirection: "row" }}> <div style={{ display: "flex", flexDirection: "row" }}>
<div className="xs:hidden flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]"> <div className="xs:hidden flex h-10 w-10 flex-shrink-0 justify-center rounded-full bg-[#FAFAFA]">
<Icon.FiEdit2 className="m-auto h-6 w-6" /> <FiEdit2 className="m-auto h-6 w-6" />
</div> </div>
<div className="mb-4 w-full px-4 pt-1"> <div className="mb-4 w-full px-4 pt-1">
<DialogHeader title={t("confirm_username_change_dialog_title")} /> <DialogHeader title={t("confirm_username_change_dialog_title")} />
@@ -2,7 +2,8 @@ import React from "react";
import { Props } from "react-select"; import { Props } from "react-select";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon, Avatar } from "@calcom/ui"; import { Avatar } from "@calcom/ui";
import { FiX } from "@calcom/ui/components/icon";
import Select from "@components/ui/form/Select"; import Select from "@components/ui/form/Select";
@@ -48,7 +49,7 @@ export const CheckedSelect = ({
alt={option.label} alt={option.label}
/> />
{option.label} {option.label}
<Icon.FiX <FiX
onClick={() => props.onChange(value.filter((item) => item.value !== option.value))} onClick={() => props.onChange(value.filter((item) => item.value !== option.value))}
className="float-right mt-0.5 h-5 w-5 cursor-pointer text-gray-500" className="float-right mt-0.5 h-5 w-5 cursor-pointer text-gray-500"
/> />
+2 -2
View File
@@ -3,7 +3,7 @@ import "react-calendar/dist/Calendar.css";
import "react-date-picker/dist/DatePicker.css"; import "react-date-picker/dist/DatePicker.css";
import PrimitiveDatePicker from "react-date-picker/dist/entry.nostyle"; import PrimitiveDatePicker from "react-date-picker/dist/entry.nostyle";
import { Icon } from "@calcom/ui"; import { FiCalendar } from "@calcom/ui/components/icon";
import classNames from "@lib/classNames"; import classNames from "@lib/classNames";
@@ -23,7 +23,7 @@ export const DatePicker = ({ minDate, disabled, date, onDatesChange, className }
className className
)} )}
clearIcon={null} clearIcon={null}
calendarIcon={<Icon.FiCalendar className="h-5 w-5 text-gray-500" />} calendarIcon={<FiCalendar className="h-5 w-5 text-gray-500" />}
value={date} value={date}
minDate={minDate} minDate={minDate}
disabled={disabled} disabled={disabled}
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@calcom/web", "name": "@calcom/web",
"version": "2.5.3", "version": "2.5.5",
"private": true, "private": true,
"scripts": { "scripts": {
"analyze": "ANALYZE=true next build", "analyze": "ANALYZE=true next build",
+13 -12
View File
@@ -4,7 +4,8 @@ import { useRouter } from "next/router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { COMPANY_NAME, DEVELOPER_DOCS, DOCS_URL, JOIN_SLACK, WEBSITE_URL } from "@calcom/lib/constants"; import { COMPANY_NAME, DEVELOPER_DOCS, DOCS_URL, JOIN_SLACK, WEBSITE_URL } from "@calcom/lib/constants";
import { Icon, HeadSeo } from "@calcom/ui"; import { HeadSeo } from "@calcom/ui";
import { FiFileText, FiCheck, FiBookOpen, FiChevronRight } from "@calcom/ui/components/icon";
import { useLocale } from "@lib/hooks/useLocale"; import { useLocale } from "@lib/hooks/useLocale";
@@ -20,13 +21,13 @@ export default function Custom404() {
{ {
title: t("documentation"), title: t("documentation"),
description: t("documentation_description"), description: t("documentation_description"),
icon: Icon.FiFileText, icon: FiFileText,
href: DOCS_URL, href: DOCS_URL,
}, },
{ {
title: t("blog"), title: t("blog"),
description: t("blog_description"), description: t("blog_description"),
icon: Icon.FiBookOpen, icon: FiBookOpen,
href: `${WEBSITE_URL}/blog`, href: `${WEBSITE_URL}/blog`,
}, },
]; ];
@@ -75,7 +76,7 @@ export default function Custom404() {
className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse"> className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50"> <span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50">
<Icon.FiCheck className="h-6 w-6 text-green-500" aria-hidden="true" /> <FiCheck className="h-6 w-6 text-green-500" aria-hidden="true" />
</span> </span>
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
@@ -90,7 +91,7 @@ export default function Custom404() {
<p className="text-base text-gray-500">{t("the_infrastructure_plan")}</p> <p className="text-base text-gray-500">{t("the_infrastructure_plan")}</p>
</div> </div>
<div className="flex-shrink-0 self-center"> <div className="flex-shrink-0 self-center">
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" /> <FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div> </div>
</a> </a>
</li> </li>
@@ -103,7 +104,7 @@ export default function Custom404() {
className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse"> className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-gray-50"> <span className="flex h-12 w-12 items-center justify-center rounded-lg bg-gray-50">
<Icon.FiFileText className="h-6 w-6 text-gray-700" aria-hidden="true" /> <FiFileText className="h-6 w-6 text-gray-700" aria-hidden="true" />
</span> </span>
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
@@ -116,7 +117,7 @@ export default function Custom404() {
<p className="text-base text-gray-500">{t("prisma_studio_tip_description")}</p> <p className="text-base text-gray-500">{t("prisma_studio_tip_description")}</p>
</div> </div>
<div className="flex-shrink-0 self-center"> <div className="flex-shrink-0 self-center">
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" /> <FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div> </div>
</Link> </Link>
</li> </li>
@@ -161,7 +162,7 @@ export default function Custom404() {
<p className="text-base text-gray-500">{t("join_our_community")}</p> <p className="text-base text-gray-500">{t("join_our_community")}</p>
</div> </div>
<div className="flex-shrink-0 self-center"> <div className="flex-shrink-0 self-center">
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" /> <FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div> </div>
</a> </a>
</li> </li>
@@ -218,7 +219,7 @@ export default function Custom404() {
rel="noreferrer"> rel="noreferrer">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50"> <span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50">
<Icon.FiCheck className="h-6 w-6 text-green-500" aria-hidden="true" /> <FiCheck className="h-6 w-6 text-green-500" aria-hidden="true" />
</span> </span>
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
@@ -233,7 +234,7 @@ export default function Custom404() {
<p className="text-base text-gray-500">{t("claim_username_and_schedule_events")}</p> <p className="text-base text-gray-500">{t("claim_username_and_schedule_events")}</p>
</div> </div>
<div className="flex-shrink-0 self-center"> <div className="flex-shrink-0 self-center">
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" /> <FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div> </div>
</a> </a>
</li> </li>
@@ -261,7 +262,7 @@ export default function Custom404() {
<p className="text-base text-gray-500">{link.description}</p> <p className="text-base text-gray-500">{link.description}</p>
</div> </div>
<div className="flex-shrink-0 self-center"> <div className="flex-shrink-0 self-center">
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" /> <FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div> </div>
</Link> </Link>
</li> </li>
@@ -307,7 +308,7 @@ export default function Custom404() {
<p className="text-base text-gray-500">{t("join_our_community")}</p> <p className="text-base text-gray-500">{t("join_our_community")}</p>
</div> </div>
<div className="flex-shrink-0 self-center"> <div className="flex-shrink-0 self-center">
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" /> <FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div> </div>
</a> </a>
</li> </li>
+3 -2
View File
@@ -3,7 +3,8 @@ import { useRouter } from "next/router";
import { APP_NAME, WEBSITE_URL } from "@calcom/lib/constants"; import { APP_NAME, WEBSITE_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, showToast } from "@calcom/ui"; import { Button, showToast } from "@calcom/ui";
import { FiCopy } from "@calcom/ui/components/icon";
export default function Error500() { export default function Error500() {
const { t } = useLocale(); const { t } = useLocale();
@@ -33,7 +34,7 @@ export default function Error500() {
<Button <Button
color="secondary" color="secondary"
className="mt-2 border-0 font-sans font-normal hover:bg-gray-300" className="mt-2 border-0 font-sans font-normal hover:bg-gray-300"
StartIcon={Icon.FiCopy} StartIcon={FiCopy}
onClick={() => { onClick={() => {
navigator.clipboard.writeText(router.query.error as string); navigator.clipboard.writeText(router.query.error as string);
showToast("Link copied!", "success"); showToast("Link copied!", "success");
+5 -4
View File
@@ -26,7 +26,8 @@ import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calco
import prisma from "@calcom/prisma"; import prisma from "@calcom/prisma";
import { baseEventTypeSelect } from "@calcom/prisma/selects"; import { baseEventTypeSelect } from "@calcom/prisma/selects";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils"; import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { Icon, HeadSeo, AvatarGroup, Avatar } from "@calcom/ui"; import { HeadSeo, AvatarGroup, Avatar } from "@calcom/ui";
import { BadgeCheckIcon, FiArrowRight } from "@calcom/ui/components/icon";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
import { EmbedProps } from "@lib/withEmbedSsr"; import { EmbedProps } from "@lib/withEmbedSsr";
@@ -55,7 +56,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps> & E
<li <li
key={index} key={index}
className="dark:bg-darkgray-100 group relative border-b border-gray-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-gray-50 dark:border-gray-700 dark:hover:border-gray-600"> className="dark:bg-darkgray-100 group relative border-b border-gray-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-gray-50 dark:border-gray-700 dark:hover:border-gray-600">
<Icon.FiArrowRight className="absolute right-3 top-3 h-4 w-4 text-black opacity-0 transition-opacity group-hover:opacity-100 dark:text-white" /> <FiArrowRight className="absolute right-3 top-3 h-4 w-4 text-black opacity-0 transition-opacity group-hover:opacity-100 dark:text-white" />
<Link <Link
href={getUsernameSlugLink({ users: props.users, slug: type.slug })} href={getUsernameSlugLink({ users: props.users, slug: type.slug })}
className="flex justify-between px-6 py-4" className="flex justify-between px-6 py-4"
@@ -134,7 +135,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps> & E
<h1 className="font-cal mb-1 text-3xl text-gray-900 dark:text-white"> <h1 className="font-cal mb-1 text-3xl text-gray-900 dark:text-white">
{nameOrUsername} {nameOrUsername}
{user.verified && ( {user.verified && (
<Icon.BadgeCheckIcon className="mx-1 -mt-1 inline h-6 w-6 text-blue-500 dark:text-white" /> <BadgeCheckIcon className="mx-1 -mt-1 inline h-6 w-6 text-blue-500 dark:text-white" />
)} )}
</h1> </h1>
<p className="dark:text-darkgray-600 text-s text-gray-500">{user.bio}</p> <p className="dark:text-darkgray-600 text-s text-gray-500">{user.bio}</p>
@@ -163,7 +164,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps> & E
key={type.id} key={type.id}
style={{ display: "flex", ...eventTypeListItemEmbedStyles }} style={{ display: "flex", ...eventTypeListItemEmbedStyles }}
className="dark:bg-darkgray-100 group relative border-b border-gray-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-gray-50 dark:border-gray-700 dark:hover:border-gray-600"> className="dark:bg-darkgray-100 group relative border-b border-gray-200 bg-white first:rounded-t-md last:rounded-b-md last:border-b-0 hover:bg-gray-50 dark:border-gray-700 dark:hover:border-gray-600">
<Icon.FiArrowRight className="absolute right-4 top-4 h-4 w-4 text-black opacity-0 transition-opacity group-hover:opacity-100 dark:text-white" /> <FiArrowRight className="absolute right-4 top-4 h-4 w-4 text-black opacity-0 transition-opacity group-hover:opacity-100 dark:text-white" />
{/* Don't prefetch till the time we drop the amount of javascript in [user][type] page which is impacting score for [user] page */} {/* Don't prefetch till the time we drop the amount of javascript in [user][type] page which is impacting score for [user] page */}
<Link <Link
prefetch={false} prefetch={false}
+4 -3
View File
@@ -4,7 +4,8 @@ import Link from "next/link";
import { getAppRegistry } from "@calcom/app-store/_appRegistry"; import { getAppRegistry } from "@calcom/app-store/_appRegistry";
import Shell from "@calcom/features/shell/Shell"; import Shell from "@calcom/features/shell/Shell";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon, SkeletonText } from "@calcom/ui"; import { SkeletonText } from "@calcom/ui";
import { FiArrowLeft, FiArrowRight } from "@calcom/ui/components/icon";
export default function Apps({ categories }: InferGetStaticPropsType<typeof getStaticProps>) { export default function Apps({ categories }: InferGetStaticPropsType<typeof getStaticProps>) {
const { t, isLocaleReady } = useLocale(); const { t, isLocaleReady } = useLocale();
@@ -15,7 +16,7 @@ export default function Apps({ categories }: InferGetStaticPropsType<typeof getS
<Link <Link
href="/apps" href="/apps"
className="inline-flex items-center justify-start gap-1 rounded-sm py-2 text-gray-900"> className="inline-flex items-center justify-start gap-1 rounded-sm py-2 text-gray-900">
<Icon.FiArrowLeft className="h-4 w-4" /> <FiArrowLeft className="h-4 w-4" />
{isLocaleReady ? t("app_store") : <SkeletonText className="h-6 w-24" />}{" "} {isLocaleReady ? t("app_store") : <SkeletonText className="h-6 w-24" />}{" "}
</Link> </Link>
</div> </div>
@@ -31,7 +32,7 @@ export default function Apps({ categories }: InferGetStaticPropsType<typeof getS
<h3 className="font-medium capitalize">{category.name}</h3> <h3 className="font-medium capitalize">{category.name}</h3>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
{t("number_apps", { count: category.count })}{" "} {t("number_apps", { count: category.count })}{" "}
<Icon.FiArrowRight className="inline-block h-4 w-4" /> <FiArrowRight className="inline-block h-4 w-4" />
</p> </p>
</div> </div>
</Link> </Link>
+2 -2
View File
@@ -12,10 +12,10 @@ import {
AppStoreCategories, AppStoreCategories,
HorizontalTabItemProps, HorizontalTabItemProps,
HorizontalTabs, HorizontalTabs,
Icon,
TextField, TextField,
PopularAppsSlider, PopularAppsSlider,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiSearch } from "@calcom/ui/components/icon";
import AppsLayout from "@components/apps/layouts/AppsLayout"; import AppsLayout from "@components/apps/layouts/AppsLayout";
@@ -42,7 +42,7 @@ function AppsSearch({
return ( return (
<TextField <TextField
className="!border-gray-100 bg-gray-100 !pl-0 focus:!ring-offset-0" className="!border-gray-100 bg-gray-100 !pl-0 focus:!ring-offset-0"
addOnLeading={<Icon.FiSearch className="h-4 w-4 text-gray-500" />} addOnLeading={<FiSearch className="h-4 w-4 text-gray-500" />}
addOnClassname="!border-gray-100" addOnClassname="!border-gray-100"
containerClassName={classNames("focus:!ring-offset-0", className)} containerClassName={classNames("focus:!ring-offset-0", className)}
type="search" type="search"
+17 -9
View File
@@ -13,11 +13,19 @@ import {
Alert, Alert,
Button, Button,
EmptyScreen, EmptyScreen,
Icon,
List, List,
AppSkeletonLoader as SkeletonLoader, AppSkeletonLoader as SkeletonLoader,
ShellSubHeading, ShellSubHeading,
} from "@calcom/ui"; } from "@calcom/ui";
import {
FiBarChart,
FiCalendar,
FiCreditCard,
FiGrid,
FiPlus,
FiShare2,
FiVideo,
} from "@calcom/ui/components/icon";
import { QueryCell } from "@lib/QueryCell"; import { QueryCell } from "@lib/QueryCell";
@@ -139,13 +147,13 @@ const IntegrationsContainer = ({ variant, exclude }: IntegrationsContainerProps)
const { t } = useLocale(); const { t } = useLocale();
const query = trpc.viewer.integrations.useQuery({ variant, exclude, onlyInstalled: true }); const query = trpc.viewer.integrations.useQuery({ variant, exclude, onlyInstalled: true });
const emptyIcon = { const emptyIcon = {
calendar: Icon.FiCalendar, calendar: FiCalendar,
conferencing: Icon.FiVideo, conferencing: FiVideo,
automation: Icon.FiShare2, automation: FiShare2,
analytics: Icon.FiBarChart, analytics: FiBarChart,
payment: Icon.FiCreditCard, payment: FiCreditCard,
web3: Icon.FiBarChart, web3: FiBarChart,
other: Icon.FiGrid, other: FiGrid,
}; };
return ( return (
@@ -169,7 +177,7 @@ const IntegrationsContainer = ({ variant, exclude }: IntegrationsContainerProps)
: "/apps" : "/apps"
} }
color="secondary" color="secondary"
StartIcon={Icon.FiPlus}> StartIcon={FiPlus}>
{t("add")} {t("add")}
</Button> </Button>
} }
+3 -2
View File
@@ -4,7 +4,8 @@ import { useRouter } from "next/router";
import z from "zod"; import z from "zod";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, SkeletonText } from "@calcom/ui"; import { Button, SkeletonText } from "@calcom/ui";
import { FiX } from "@calcom/ui/components/icon";
import AuthContainer from "@components/ui/AuthContainer"; import AuthContainer from "@components/ui/AuthContainer";
@@ -28,7 +29,7 @@ export default function Error() {
<AuthContainer title="" description=""> <AuthContainer title="" description="">
<div> <div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
<Icon.FiX className="h-6 w-6 text-red-600" /> <FiX className="h-6 w-6 text-red-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title">
+3 -2
View File
@@ -13,7 +13,8 @@ import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import prisma from "@calcom/prisma"; import prisma from "@calcom/prisma";
import { Alert, Button, EmailField, Icon, PasswordField } from "@calcom/ui"; import { Alert, Button, EmailField, PasswordField } from "@calcom/ui";
import { FiArrowLeft } from "@calcom/ui/components/icon";
import { ErrorCode, getSession } from "@lib/auth"; import { ErrorCode, getSession } from "@lib/auth";
import { WEBAPP_URL, WEBSITE_URL } from "@lib/config/constants"; import { WEBAPP_URL, WEBSITE_URL } from "@lib/config/constants";
@@ -85,7 +86,7 @@ export default function Login({
setTwoFactorRequired(false); setTwoFactorRequired(false);
methods.setValue("totpCode", ""); methods.setValue("totpCode", "");
}} }}
StartIcon={Icon.FiArrowLeft} StartIcon={FiArrowLeft}
color="minimal"> color="minimal">
{t("go_back")} {t("go_back")}
</Button> </Button>
+3 -2
View File
@@ -5,7 +5,8 @@ import { useEffect } from "react";
import { WEBSITE_URL } from "@calcom/lib/constants"; import { WEBSITE_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon } from "@calcom/ui"; import { Button } from "@calcom/ui";
import { FiCheck } from "@calcom/ui/components/icon";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -31,7 +32,7 @@ export default function Logout(props: Props) {
<AuthContainer title={t("logged_out")} description={t("youve_been_logged_out")} showLogo> <AuthContainer title={t("logged_out")} description={t("youve_been_logged_out")} showLogo>
<div className="mb-4"> <div className="mb-4">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
<Icon.FiCheck className="h-6 w-6 text-green-600" /> <FiCheck className="h-6 w-6 text-green-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title">
+2 -2
View File
@@ -1,7 +1,7 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon } from "@calcom/ui"; import { FiCheck } from "@calcom/ui/components/icon";
const StepDone = () => { const StepDone = () => {
const router = useRouter(); const router = useRouter();
@@ -18,7 +18,7 @@ const StepDone = () => {
}}> }}>
<div className="min-h-36 my-6 flex flex-col items-center justify-center"> <div className="min-h-36 my-6 flex flex-col items-center justify-center">
<div className="flex h-[72px] w-[72px] items-center justify-center rounded-full bg-gray-600 dark:bg-white"> <div className="flex h-[72px] w-[72px] items-center justify-center rounded-full bg-gray-600 dark:bg-white">
<Icon.FiCheck className="inline-block h-10 w-10 text-white dark:bg-white dark:text-gray-600" /> <FiCheck className="inline-block h-10 w-10 text-white dark:bg-white dark:text-gray-600" />
</div> </div>
<div className="max-w-[420px] text-center"> <div className="max-w-[420px] text-center">
<h2 className="mt-6 mb-1 text-lg font-medium dark:text-gray-300">{t("all_done")}</h2> <h2 className="mt-6 mb-1 text-lg font-medium dark:text-gray-300">{t("all_done")}</h2>
+3 -3
View File
@@ -15,7 +15,6 @@ import type { Schedule as ScheduleType, TimeRange, WorkingHours } from "@calcom/
import { import {
Button, Button,
Form, Form,
Icon,
Label, Label,
showToast, showToast,
Skeleton, Skeleton,
@@ -25,6 +24,7 @@ import {
Tooltip, Tooltip,
VerticalDivider, VerticalDivider,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiInfo, FiPlus } from "@calcom/ui/components/icon";
import { HttpError } from "@lib/core/http/error"; import { HttpError } from "@lib/core/http/error";
@@ -56,7 +56,7 @@ const DateOverride = ({ workingHours }: { workingHours: WorkingHours[] }) => {
{t("date_overrides")}{" "} {t("date_overrides")}{" "}
<Tooltip content={t("date_overrides_info")}> <Tooltip content={t("date_overrides_info")}>
<span className="inline-block"> <span className="inline-block">
<Icon.FiInfo /> <FiInfo />
</span> </span>
</Tooltip> </Tooltip>
</h3> </h3>
@@ -74,7 +74,7 @@ const DateOverride = ({ workingHours }: { workingHours: WorkingHours[] }) => {
excludedDates={fields.map((field) => yyyymmdd(field.ranges[0].start))} excludedDates={fields.map((field) => yyyymmdd(field.ranges[0].start))}
onChange={(ranges) => append({ ranges })} onChange={(ranges) => append({ ranges })}
Trigger={ Trigger={
<Button color="secondary" StartIcon={Icon.FiPlus} data-testid="add-override"> <Button color="secondary" StartIcon={FiPlus} data-testid="add-override">
Add an override Add an override
</Button> </Button>
} }
+3 -2
View File
@@ -5,7 +5,8 @@ import { NewScheduleButton, ScheduleListItem } from "@calcom/features/schedules"
import Shell from "@calcom/features/shell/Shell"; import Shell from "@calcom/features/shell/Shell";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { RouterOutputs, trpc } from "@calcom/trpc/react";
import { EmptyScreen, Icon, showToast } from "@calcom/ui"; import { EmptyScreen, showToast } from "@calcom/ui";
import { FiClock } from "@calcom/ui/components/icon";
import { withQuery } from "@lib/QueryCell"; import { withQuery } from "@lib/QueryCell";
import { HttpError } from "@lib/core/http/error"; import { HttpError } from "@lib/core/http/error";
@@ -76,7 +77,7 @@ export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availab
{schedules.length === 0 ? ( {schedules.length === 0 ? (
<div className="flex justify-center"> <div className="flex justify-center">
<EmptyScreen <EmptyScreen
Icon={Icon.FiClock} Icon={FiClock}
headline={t("new_schedule_heading")} headline={t("new_schedule_heading")}
description={t("new_schedule_description")} description={t("new_schedule_description")}
buttonRaw={<NewScheduleButton />} buttonRaw={<NewScheduleButton />}
+7 -6
View File
@@ -35,7 +35,8 @@ import { localStorage } from "@calcom/lib/webstorage";
import prisma from "@calcom/prisma"; import prisma from "@calcom/prisma";
import { Prisma } from "@calcom/prisma/client"; import { Prisma } from "@calcom/prisma/client";
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils"; import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { Button, EmailInput, Icon, HeadSeo } from "@calcom/ui"; import { Button, EmailInput, HeadSeo } from "@calcom/ui";
import { FiX, FiChevronLeft, FiCheck, FiCalendar } from "@calcom/ui/components/icon";
import { timeZone } from "@lib/clock"; import { timeZone } from "@lib/clock";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -142,7 +143,7 @@ function RedirectionToast({ url }: { url: string }) {
setIsToastVisible(false); setIsToastVisible(false);
}} }}
className="-mr-1 flex rounded-md p-2 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-white"> className="-mr-1 flex rounded-md p-2 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-white">
<Icon.FiX className="h-6 w-6 text-white" /> <FiX className="h-6 w-6 text-white" />
</button> </button>
</div> </div>
</div> </div>
@@ -356,7 +357,7 @@ export default function Success(props: SuccessProps) {
<Link <Link
href={allRemainingBookings ? "/bookings/recurring" : "/bookings/upcoming"} href={allRemainingBookings ? "/bookings/recurring" : "/bookings/upcoming"}
className="mt-2 inline-flex px-1 py-2 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-transparent dark:hover:text-white"> className="mt-2 inline-flex px-1 py-2 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-transparent dark:hover:text-white">
<Icon.FiChevronLeft className="h-5 w-5" /> {t("back_to_bookings")} <FiChevronLeft className="h-5 w-5" /> {t("back_to_bookings")}
</Link> </Link>
</div> </div>
)} )}
@@ -401,10 +402,10 @@ export default function Success(props: SuccessProps) {
<img src={giphyImage} alt="Gif from Giphy" /> <img src={giphyImage} alt="Gif from Giphy" />
)} )}
{!giphyImage && !needsConfirmation && !isCancelled && ( {!giphyImage && !needsConfirmation && !isCancelled && (
<Icon.FiCheck className="h-5 w-5 text-green-600" /> <FiCheck className="h-5 w-5 text-green-600" />
)} )}
{needsConfirmation && !isCancelled && <Icon.FiCalendar className="h-5 w-5 text-gray-900" />} {needsConfirmation && !isCancelled && <FiCalendar className="h-5 w-5 text-gray-900" />}
{isCancelled && <Icon.FiX className="h-5 w-5 text-red-600" />} {isCancelled && <FiX className="h-5 w-5 text-red-600" />}
</div> </div>
<div className="mt-6 mb-8 text-center last:mb-0"> <div className="mt-6 mb-8 text-center last:mb-0">
<h3 <h3
+3 -2
View File
@@ -9,7 +9,8 @@ import BookingLayout from "@calcom/features/bookings/layout/BookingLayout";
import { filterQuerySchema, useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery"; import { filterQuerySchema, useFilterQuery } from "@calcom/features/bookings/lib/useFilterQuery";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { RouterOutputs, trpc } from "@calcom/trpc/react";
import { Alert, Button, EmptyScreen, Icon } from "@calcom/ui"; import { Alert, Button, EmptyScreen } from "@calcom/ui";
import { FiCalendar } from "@calcom/ui/components/icon";
import { useInViewObserver } from "@lib/hooks/useInViewObserver"; import { useInViewObserver } from "@lib/hooks/useInViewObserver";
@@ -176,7 +177,7 @@ export default function Bookings() {
{query.status === "success" && isEmpty && ( {query.status === "success" && isEmpty && (
<div className="flex items-center justify-center pt-2 xl:pt-0"> <div className="flex items-center justify-center pt-2 xl:pt-0">
<EmptyScreen <EmptyScreen
Icon={Icon.FiCalendar} Icon={FiCalendar}
headline={t("no_status_bookings_yet", { status: t(status).toLowerCase() })} headline={t("no_status_bookings_yet", { status: t(status).toLowerCase() })}
description={t("no_status_bookings_yet_description", { description={t("no_status_bookings_yet_description", {
status: t(status).toLowerCase(), status: t(status).toLowerCase(),
+40 -32
View File
@@ -26,13 +26,27 @@ import {
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
EmptyScreen, EmptyScreen,
Icon,
showToast, showToast,
Switch, Switch,
Avatar, Avatar,
AvatarGroup, AvatarGroup,
Tooltip, Tooltip,
} from "@calcom/ui"; } from "@calcom/ui";
import {
FiArrowDown,
FiArrowUp,
FiClipboard,
FiCode,
FiCopy,
FiEdit,
FiEdit2,
FiExternalLink,
FiLink,
FiMoreHorizontal,
FiTrash,
FiUpload,
FiUsers,
} from "@calcom/ui/components/icon";
import { withQuery } from "@lib/QueryCell"; import { withQuery } from "@lib/QueryCell";
import { HttpError } from "@lib/core/http/error"; import { HttpError } from "@lib/core/http/error";
@@ -263,7 +277,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<button <button
className="invisible absolute left-[5px] -mt-4 mb-4 -ml-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border bg-white p-1 text-gray-400 transition-all hover:border-transparent hover:text-black hover:shadow disabled:hover:border-inherit disabled:hover:text-gray-400 disabled:hover:shadow-none group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[36px]" className="invisible absolute left-[5px] -mt-4 mb-4 -ml-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border bg-white p-1 text-gray-400 transition-all hover:border-transparent hover:text-black hover:shadow disabled:hover:border-inherit disabled:hover:text-gray-400 disabled:hover:shadow-none group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[36px]"
onClick={() => moveEventType(index, -1)}> onClick={() => moveEventType(index, -1)}>
<Icon.FiArrowUp className="h-5 w-5" /> <FiArrowUp className="h-5 w-5" />
</button> </button>
)} )}
@@ -271,7 +285,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<button <button
className="invisible absolute left-[5px] mt-8 -ml-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border bg-white p-1 text-gray-400 transition-all hover:border-transparent hover:text-black hover:shadow disabled:hover:border-inherit disabled:hover:text-gray-400 disabled:hover:shadow-none group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[36px]" className="invisible absolute left-[5px] mt-8 -ml-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border bg-white p-1 text-gray-400 transition-all hover:border-transparent hover:text-black hover:shadow disabled:hover:border-inherit disabled:hover:text-gray-400 disabled:hover:shadow-none group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[36px]"
onClick={() => moveEventType(index, 1)}> onClick={() => moveEventType(index, 1)}>
<Icon.FiArrowDown className="h-5 w-5" /> <FiArrowDown className="h-5 w-5" />
</button> </button>
)} )}
<MemoizedItem type={type} group={group} readOnly={readOnly} /> <MemoizedItem type={type} group={group} readOnly={readOnly} />
@@ -314,7 +328,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
target="_blank" target="_blank"
variant="icon" variant="icon"
href={calLink} href={calLink}
StartIcon={Icon.FiExternalLink} StartIcon={FiExternalLink}
/> />
</Tooltip> </Tooltip>
@@ -322,7 +336,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<Button <Button
color="secondary" color="secondary"
variant="icon" variant="icon"
StartIcon={Icon.FiLink} StartIcon={FiLink}
onClick={() => { onClick={() => {
showToast(t("link_copied"), "success"); showToast(t("link_copied"), "success");
navigator.clipboard.writeText(calLink); navigator.clipboard.writeText(calLink);
@@ -338,7 +352,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
type="button" type="button"
variant="icon" variant="icon"
color="secondary" color="secondary"
StartIcon={Icon.FiMoreHorizontal} StartIcon={FiMoreHorizontal}
/> />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
@@ -346,7 +360,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<DropdownItem <DropdownItem
type="button" type="button"
data-testid={"event-type-edit-" + type.id} data-testid={"event-type-edit-" + type.id}
StartIcon={Icon.FiEdit2} StartIcon={FiEdit2}
onClick={() => router.push("/event-types/" + type.id)}> onClick={() => router.push("/event-types/" + type.id)}>
{t("edit")} {t("edit")}
</DropdownItem> </DropdownItem>
@@ -355,7 +369,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<DropdownItem <DropdownItem
type="button" type="button"
data-testid={"event-type-duplicate-" + type.id} data-testid={"event-type-duplicate-" + type.id}
StartIcon={Icon.FiCopy} StartIcon={FiCopy}
onClick={() => openDuplicateModal(type)}> onClick={() => openDuplicateModal(type)}>
{t("duplicate")} {t("duplicate")}
</DropdownItem> </DropdownItem>
@@ -364,7 +378,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<EmbedButton <EmbedButton
as={DropdownItem} as={DropdownItem}
type="button" type="button"
StartIcon={Icon.FiCode} StartIcon={FiCode}
className="w-full rounded-none" className="w-full rounded-none"
embedUrl={encodeURIComponent(embedLink)}> embedUrl={encodeURIComponent(embedLink)}>
{t("embed")} {t("embed")}
@@ -380,7 +394,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
setDeleteDialogOpen(true); setDeleteDialogOpen(true);
setDeleteDialogTypeId(type.id); setDeleteDialogTypeId(type.id);
}} }}
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
className="w-full rounded-none"> className="w-full rounded-none">
{t("delete")} {t("delete")}
</DropdownItem> </DropdownItem>
@@ -396,12 +410,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<div className="min-w-9 mx-5 flex sm:hidden"> <div className="min-w-9 mx-5 flex sm:hidden">
<Dropdown> <Dropdown>
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}> <DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}>
<Button <Button type="button" variant="icon" color="secondary" StartIcon={FiMoreHorizontal} />
type="button"
variant="icon"
color="secondary"
StartIcon={Icon.FiMoreHorizontal}
/>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuPortal> <DropdownMenuPortal>
<DropdownMenuContent> <DropdownMenuContent>
@@ -409,7 +418,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
<Link href={calLink} target="_blank"> <Link href={calLink} target="_blank">
<Button <Button
color="minimal" color="minimal"
StartIcon={Icon.FiExternalLink} StartIcon={FiExternalLink}
className="w-full rounded-none"> className="w-full rounded-none">
{t("preview")} {t("preview")}
</Button> </Button>
@@ -421,7 +430,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
color="minimal" color="minimal"
className="w-full rounded-none text-left" className="w-full rounded-none text-left"
data-testid={"event-type-duplicate-" + type.id} data-testid={"event-type-duplicate-" + type.id}
StartIcon={Icon.FiClipboard} StartIcon={FiClipboard}
onClick={() => { onClick={() => {
navigator.clipboard.writeText(calLink); navigator.clipboard.writeText(calLink);
showToast(t("link_copied"), "success"); showToast(t("link_copied"), "success");
@@ -436,7 +445,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
color="minimal" color="minimal"
className="w-full rounded-none" className="w-full rounded-none"
data-testid={"event-type-duplicate-" + type.id} data-testid={"event-type-duplicate-" + type.id}
StartIcon={Icon.FiUpload} StartIcon={FiUpload}
onClick={() => { onClick={() => {
navigator navigator
.share({ .share({
@@ -457,7 +466,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
onClick={() => router.push("/event-types/" + type.id)} onClick={() => router.push("/event-types/" + type.id)}
color="minimal" color="minimal"
className="w-full rounded-none" className="w-full rounded-none"
StartIcon={Icon.FiEdit}> StartIcon={FiEdit}>
{t("edit")} {t("edit")}
</Button> </Button>
</DropdownMenuItem> </DropdownMenuItem>
@@ -467,7 +476,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
color="minimal" color="minimal"
className="w-full rounded-none" className="w-full rounded-none"
data-testid={"event-type-duplicate-" + type.id} data-testid={"event-type-duplicate-" + type.id}
StartIcon={Icon.FiCopy} StartIcon={FiCopy}
onClick={() => openDuplicateModal(type)}> onClick={() => openDuplicateModal(type)}>
{t("duplicate")} {t("duplicate")}
</Button> </Button>
@@ -480,7 +489,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
setDeleteDialogTypeId(type.id); setDeleteDialogTypeId(type.id);
}} }}
color="destructive" color="destructive"
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
className="w-full rounded-none"> className="w-full rounded-none">
{t("delete")} {t("delete")}
</Button> </Button>
@@ -518,14 +527,13 @@ const EventTypeListHeading = ({
}: EventTypeListHeadingProps): JSX.Element => { }: EventTypeListHeadingProps): JSX.Element => {
return ( return (
<div className="mb-4 flex items-center space-x-2"> <div className="mb-4 flex items-center space-x-2">
<Link href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}> <Avatar
<Avatar alt={profile?.name || ""}
alt={profile?.name || ""} href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}
imageSrc={`${WEBAPP_URL}/${profile.slug}/avatar.png` || undefined} imageSrc={`${WEBAPP_URL}/${profile.slug}/avatar.png` || undefined}
size="sm" size="md"
className="mt-1 inline ltr:mr-2 rtl:ml-2" className="mt-1 inline-flex justify-center"
/> />
</Link>
<div> <div>
<Link <Link
href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"} href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}
@@ -536,7 +544,7 @@ const EventTypeListHeading = ({
<span className="relative -top-px text-xs text-gray-500 ltr:ml-2 ltr:mr-2 rtl:ml-2"> <span className="relative -top-px text-xs text-gray-500 ltr:ml-2 ltr:mr-2 rtl:ml-2">
<Link href={`/settings/teams/${teamId}/members`}> <Link href={`/settings/teams/${teamId}/members`}>
<Badge variant="gray"> <Badge variant="gray">
<Icon.FiUsers className="mr-1 -mt-px inline h-3 w-3" /> <FiUsers className="mr-1 -mt-px inline h-3 w-3" />
{membershipCount} {membershipCount}
</Badge> </Badge>
</Link> </Link>
@@ -557,7 +565,7 @@ const CreateFirstEventTypeView = () => {
return ( return (
<EmptyScreen <EmptyScreen
Icon={Icon.FiLink} Icon={FiLink}
headline={t("new_event_type_heading")} headline={t("new_event_type_heading")}
description={t("new_event_type_description")} description={t("new_event_type_description")}
/> />
+3 -2
View File
@@ -8,7 +8,8 @@ import { classNames } from "@calcom/lib";
import { WEBAPP_URL } from "@calcom/lib/constants"; import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, Icon, Meta } from "@calcom/ui"; import { Button, Meta } from "@calcom/ui";
import { FiExternalLink } from "@calcom/ui/components/icon";
import { ssrInit } from "@server/lib/ssr"; import { ssrInit } from "@server/lib/ssr";
@@ -55,7 +56,7 @@ const BillingView = () => {
<CtaRow <CtaRow
title={t("billing_manage_details_title")} title={t("billing_manage_details_title")}
description={t("billing_manage_details_description")}> description={t("billing_manage_details_description")}>
<Button color="primary" href={billingHref} target="_blank" EndIcon={Icon.FiExternalLink}> <Button color="primary" href={billingHref} target="_blank" EndIcon={FiExternalLink}>
{t("billing_portal")} {t("billing_portal")}
</Button> </Button>
</CtaRow> </CtaRow>
@@ -14,10 +14,10 @@ import {
Dialog, Dialog,
DialogContent, DialogContent,
EmptyScreen, EmptyScreen,
Icon,
Meta, Meta,
AppSkeletonLoader as SkeletonLoader, AppSkeletonLoader as SkeletonLoader,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiLink, FiPlus } from "@calcom/ui/components/icon";
import { ssrInit } from "@server/lib/ssr"; import { ssrInit } from "@server/lib/ssr";
@@ -35,7 +35,7 @@ const ApiKeysView = () => {
return ( return (
<Button <Button
color="secondary" color="secondary"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
onClick={() => { onClick={() => {
setApiKeyToEdit(undefined); setApiKeyToEdit(undefined);
setApiKeyModal(true); setApiKeyModal(true);
@@ -75,7 +75,7 @@ const ApiKeysView = () => {
</> </>
) : ( ) : (
<EmptyScreen <EmptyScreen
Icon={Icon.FiLink} Icon={FiLink}
headline={t("create_first_api_key")} headline={t("create_first_api_key")}
description={t("create_first_api_key_description", { appName: APP_NAME })} description={t("create_first_api_key_description", { appName: APP_NAME })}
buttonRaw={<NewApiKeyButton />} buttonRaw={<NewApiKeyButton />}
@@ -4,6 +4,7 @@ import { Controller, useForm } from "react-hook-form";
import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout";
import { APP_NAME } from "@calcom/lib/constants"; import { APP_NAME } from "@calcom/lib/constants";
import { useHasTeamPlan } from "@calcom/lib/hooks/useHasTeamPlan";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { import {
@@ -49,7 +50,8 @@ const AppearanceView = () => {
const session = useSession(); const session = useSession();
const utils = trpc.useContext(); const utils = trpc.useContext();
const { data: user, isLoading } = trpc.viewer.me.useQuery(); const { data: user, isLoading } = trpc.viewer.me.useQuery();
const { data: dataHasTeamPlan, isLoading: isLoadingHasTeamPlan } = trpc.viewer.teams.hasTeamPlan.useQuery();
const { isLoading: isTeamPlanStatusLoading, hasTeamPlan } = useHasTeamPlan();
const formMethods = useForm({ const formMethods = useForm({
defaultValues: { defaultValues: {
@@ -74,7 +76,7 @@ const AppearanceView = () => {
}, },
}); });
if (isLoading || isLoadingHasTeamPlan) if (isLoading || isTeamPlanStatusLoading)
return <SkeletonLoader title={t("appearance")} description={t("appearance_description")} />; return <SkeletonLoader title={t("appearance")} description={t("appearance_description")} />;
if (!user) return null; if (!user) return null;
@@ -164,7 +166,7 @@ const AppearanceView = () => {
{/* TODO future PR to preview brandColors */} {/* TODO future PR to preview brandColors */}
{/* <Button {/* <Button
color="secondary" color="secondary"
EndIcon={Icon.FiExternalLink} EndIcon={FiExternalLink}
className="mt-6" className="mt-6"
onClick={() => window.open(`${WEBAPP_URL}/${user.username}/${user.eventTypes[0].title}`, "_blank")}> onClick={() => window.open(`${WEBAPP_URL}/${user.username}/${user.eventTypes[0].title}`, "_blank")}>
Preview Preview
@@ -182,18 +184,18 @@ const AppearanceView = () => {
<p className="font-semibold ltr:mr-2 rtl:ml-2"> <p className="font-semibold ltr:mr-2 rtl:ml-2">
{t("disable_cal_branding", { appName: APP_NAME })} {t("disable_cal_branding", { appName: APP_NAME })}
</p> </p>
{!dataHasTeamPlan?.hasTeamPlan && <UpgradeTeamsBadge />} <UpgradeTeamsBadge />
</div> </div>
<p className="mt-0.5 text-gray-600">{t("removes_cal_branding", { appName: APP_NAME })}</p> <p className="mt-0.5 text-gray-600">{t("removes_cal_branding", { appName: APP_NAME })}</p>
</div> </div>
<div className="flex-none"> <div className="flex-none">
<Switch <Switch
id="hideBranding" id="hideBranding"
disabled={!dataHasTeamPlan?.hasTeamPlan} disabled={!hasTeamPlan}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
formMethods.setValue("hideBranding", checked, { shouldDirty: true }) formMethods.setValue("hideBranding", checked, { shouldDirty: true })
} }
checked={!dataHasTeamPlan?.hasTeamPlan ? false : value} checked={hasTeamPlan ? value : false}
/> />
</div> </div>
</div> </div>
@@ -14,7 +14,6 @@ import {
Badge, Badge,
Button, Button,
EmptyScreen, EmptyScreen,
Icon,
List, List,
ListItem, ListItem,
ListItemText, ListItemText,
@@ -25,6 +24,7 @@ import {
SkeletonText, SkeletonText,
showToast, showToast,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiPlus, FiCalendar } from "@calcom/ui/components/icon";
import { QueryCell } from "@lib/QueryCell"; import { QueryCell } from "@lib/QueryCell";
@@ -52,7 +52,7 @@ const AddCalendarButton = () => {
return ( return (
<> <>
<Button color="secondary" StartIcon={Icon.FiPlus} href="/apps/categories/calendar"> <Button color="secondary" StartIcon={FiPlus} href="/apps/categories/calendar">
{t("add_calendar")} {t("add_calendar")}
</Button> </Button>
</> </>
@@ -89,7 +89,7 @@ const CalendarsView = () => {
<div> <div>
<div className="mt-4 flex space-x-4 rounded-md border-gray-200 bg-gray-50 p-2 sm:mx-0 sm:p-10 md:border md:p-6 xl:mt-0"> <div className="mt-4 flex space-x-4 rounded-md border-gray-200 bg-gray-50 p-2 sm:mx-0 sm:p-10 md:border md:p-6 xl:mt-0">
<div className=" flex h-9 w-9 items-center justify-center rounded-md border-2 border-gray-200 bg-white p-[6px]"> <div className=" flex h-9 w-9 items-center justify-center rounded-md border-2 border-gray-200 bg-white p-[6px]">
<Icon.FiCalendar className="h-6 w-6" /> <FiCalendar className="h-6 w-6" />
</div> </div>
<div className="flex w-full flex-col space-y-3"> <div className="flex w-full flex-col space-y-3">
@@ -197,7 +197,7 @@ const CalendarsView = () => {
</div> </div>
) : ( ) : (
<EmptyScreen <EmptyScreen
Icon={Icon.FiCalendar} Icon={FiCalendar}
headline={t("no_calendar_installed")} headline={t("no_calendar_installed")}
description={t("no_calendar_installed_description")} description={t("no_calendar_installed_description")}
buttonText={t("add_a_calendar")} buttonText={t("add_a_calendar")}
@@ -15,13 +15,13 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownItem, DropdownItem,
DropdownMenuTrigger, DropdownMenuTrigger,
Icon,
List, List,
Meta, Meta,
showToast, showToast,
SkeletonContainer, SkeletonContainer,
SkeletonText, SkeletonText,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiAlertCircle, FiMoreHorizontal, FiTrash } from "@calcom/ui/components/icon";
import AppListCard from "@components/AppListCard"; import AppListCard from "@components/AppListCard";
@@ -85,7 +85,7 @@ const ConferencingLayout = () => {
<div> <div>
<Dropdown> <Dropdown>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button StartIcon={Icon.FiMoreHorizontal} variant="icon" color="secondary" /> <Button StartIcon={FiMoreHorizontal} variant="icon" color="secondary" />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
<DropdownMenuItem> <DropdownMenuItem>
@@ -93,7 +93,7 @@ const ConferencingLayout = () => {
type="button" type="button"
color="destructive" color="destructive"
disabled={app.isGlobal} disabled={app.isGlobal}
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
onClick={() => { onClick={() => {
setDeleteCredentialId(app.credentialIds[0]); setDeleteCredentialId(app.credentialIds[0]);
setDeleteAppModal(true); setDeleteAppModal(true);
@@ -114,7 +114,7 @@ const ConferencingLayout = () => {
title={t("Remove app")} title={t("Remove app")}
description={t("are_you_sure_you_want_to_remove_this_app")} description={t("are_you_sure_you_want_to_remove_this_app")}
type="confirmation" type="confirmation"
Icon={Icon.FiAlertCircle}> Icon={FiAlertCircle}>
<DialogFooter> <DialogFooter>
<Button color="primary" onClick={() => deleteAppMutation.mutate({ id: deleteCredentialId })}> <Button color="primary" onClick={() => deleteAppMutation.mutate({ id: deleteCredentialId })}>
{t("yes_remove_app")} {t("yes_remove_app")}
@@ -22,7 +22,6 @@ import {
DialogFooter, DialogFooter,
DialogTrigger, DialogTrigger,
Form, Form,
Icon,
ImageUploader, ImageUploader,
Label, Label,
Meta, Meta,
@@ -34,6 +33,7 @@ import {
SkeletonText, SkeletonText,
TextField, TextField,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiAlertTriangle, FiTrash2 } from "@calcom/ui/components/icon";
import TwoFactor from "@components/auth/TwoFactor"; import TwoFactor from "@components/auth/TwoFactor";
import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability"; import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability";
@@ -229,7 +229,7 @@ const ProfileView = () => {
{/* Delete account Dialog */} {/* Delete account Dialog */}
<Dialog open={deleteAccountOpen} onOpenChange={setDeleteAccountOpen}> <Dialog open={deleteAccountOpen} onOpenChange={setDeleteAccountOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button data-testid="delete-account" color="destructive" className="mt-1" StartIcon={Icon.FiTrash2}> <Button data-testid="delete-account" color="destructive" className="mt-1" StartIcon={FiTrash2}>
{t("delete_account")} {t("delete_account")}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
@@ -237,7 +237,7 @@ const ProfileView = () => {
title={t("delete_account_modal_title")} title={t("delete_account_modal_title")}
description={t("confirm_delete_account_modal", { appName: APP_NAME })} description={t("confirm_delete_account_modal", { appName: APP_NAME })}
type="creation" type="creation"
Icon={Icon.FiAlertTriangle}> Icon={FiAlertTriangle}>
<> <>
<p className="mb-7">{t("delete_account_confirmation_message", { appName: APP_NAME })}</p> <p className="mb-7">{t("delete_account_confirmation_message", { appName: APP_NAME })}</p>
{isCALIdentityProviver && ( {isCALIdentityProviver && (
@@ -278,7 +278,7 @@ const ProfileView = () => {
title={t("confirm_password")} title={t("confirm_password")}
description={t("confirm_password_change_email")} description={t("confirm_password_change_email")}
type="creation" type="creation"
Icon={Icon.FiAlertTriangle}> Icon={FiAlertTriangle}>
<> <>
<PasswordField <PasswordField
data-testid="password" data-testid="password"
+3 -2
View File
@@ -12,7 +12,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import useTheme from "@calcom/lib/hooks/useTheme"; import useTheme from "@calcom/lib/hooks/useTheme";
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams"; import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { Avatar, Button, Icon, HeadSeo, AvatarGroup } from "@calcom/ui"; import { Avatar, Button, HeadSeo, AvatarGroup } from "@calcom/ui";
import { FiArrowRight } from "@calcom/ui/components/icon";
import { useToggleQuery } from "@lib/hooks/useToggleQuery"; import { useToggleQuery } from "@lib/hooks/useToggleQuery";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -113,7 +114,7 @@ function TeamPage({ team }: TeamPageProps) {
<aside className="mt-8 flex justify-center text-center dark:text-white"> <aside className="mt-8 flex justify-center text-center dark:text-white">
<Button <Button
color="minimal" color="minimal"
EndIcon={Icon.FiArrowRight} EndIcon={FiArrowRight}
className="dark:hover:bg-darkgray-200" className="dark:hover:bg-darkgray-200"
href={`/team/${team.slug}?members=1`} href={`/team/${team.slug}?members=1`}
shallow={true}> shallow={true}>
+3 -2
View File
@@ -4,7 +4,8 @@ import { TeamsListing } from "@calcom/features/ee/teams/components";
import Shell from "@calcom/features/shell/Shell"; import Shell from "@calcom/features/shell/Shell";
import { WEBAPP_URL } from "@calcom/lib/constants"; import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon } from "@calcom/ui"; import { Button } from "@calcom/ui";
import { FiPlus } from "@calcom/ui/components/icon";
import { ssrInit } from "@server/lib/ssr"; import { ssrInit } from "@server/lib/ssr";
@@ -17,7 +18,7 @@ function Teams() {
CTA={ CTA={
<Button <Button
variant="fab" variant="fab"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
type="button" type="button"
href={`${WEBAPP_URL}/settings/teams/new?returnTo=${WEBAPP_URL}/teams`}> href={`${WEBAPP_URL}/settings/teams/new?returnTo=${WEBAPP_URL}/teams`}>
{t("new")} {t("new")}
+5 -4
View File
@@ -4,7 +4,8 @@ import dayjs from "@calcom/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat"; import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat";
import prisma, { bookingMinimalSelect } from "@calcom/prisma"; import prisma, { bookingMinimalSelect } from "@calcom/prisma";
import { Button, Icon, HeadSeo } from "@calcom/ui"; import { Button, HeadSeo } from "@calcom/ui";
import { FiArrowRight, FiCalendar, FiX } from "@calcom/ui/components/icon";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -28,7 +29,7 @@ export default function MeetingUnavailable(props: inferSSRProps<typeof getServer
aria-labelledby="modal-headline"> aria-labelledby="modal-headline">
<div> <div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
<Icon.FiX className="h-6 w-6 text-red-600" /> <FiX className="h-6 w-6 text-red-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
@@ -40,14 +41,14 @@ export default function MeetingUnavailable(props: inferSSRProps<typeof getServer
{props.booking.title} {props.booking.title}
</h2> </h2>
<p className="text-center text-gray-500"> <p className="text-center text-gray-500">
<Icon.FiCalendar className="mr-1 -mt-1 inline-block h-4 w-4" /> <FiCalendar className="mr-1 -mt-1 inline-block h-4 w-4" />
{dayjs(props.booking.startTime).format(detectBrowserTimeFormat + ", dddd DD MMMM YYYY")} {dayjs(props.booking.startTime).format(detectBrowserTimeFormat + ", dddd DD MMMM YYYY")}
</p> </p>
</div> </div>
</div> </div>
<div className="mt-5 text-center sm:mt-6"> <div className="mt-5 text-center sm:mt-6">
<div className="mt-5"> <div className="mt-5">
<Button data-testid="return-home" href="/event-types" EndIcon={Icon.FiArrowRight}> <Button data-testid="return-home" href="/event-types" EndIcon={FiArrowRight}>
{t("go_back")} {t("go_back")}
</Button> </Button>
</div> </div>
@@ -5,7 +5,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat"; import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat";
import prisma, { bookingMinimalSelect } from "@calcom/prisma"; import prisma, { bookingMinimalSelect } from "@calcom/prisma";
import type { inferSSRProps } from "@calcom/types/inferSSRProps"; import type { inferSSRProps } from "@calcom/types/inferSSRProps";
import { Button, Icon, HeadSeo } from "@calcom/ui"; import { Button, HeadSeo } from "@calcom/ui";
import { FiArrowRight, FiCalendar, FiX } from "@calcom/ui/components/icon";
export default function MeetingNotStarted(props: inferSSRProps<typeof getServerSideProps>) { export default function MeetingNotStarted(props: inferSSRProps<typeof getServerSideProps>) {
const { t } = useLocale(); const { t } = useLocale();
@@ -26,7 +27,7 @@ export default function MeetingNotStarted(props: inferSSRProps<typeof getServerS
aria-labelledby="modal-headline"> aria-labelledby="modal-headline">
<div> <div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
<Icon.FiX className="h-6 w-6 text-red-600" /> <FiX className="h-6 w-6 text-red-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
@@ -38,7 +39,7 @@ export default function MeetingNotStarted(props: inferSSRProps<typeof getServerS
{props.booking.title} {props.booking.title}
</h2> </h2>
<p className="text-center text-gray-500"> <p className="text-center text-gray-500">
<Icon.FiCalendar className="mr-1 -mt-1 inline-block h-4 w-4" /> <FiCalendar className="mr-1 -mt-1 inline-block h-4 w-4" />
{dayjs(props.booking.startTime).format(detectBrowserTimeFormat + ", dddd DD MMMM YYYY")} {dayjs(props.booking.startTime).format(detectBrowserTimeFormat + ", dddd DD MMMM YYYY")}
</p> </p>
</div> </div>
@@ -50,7 +51,7 @@ export default function MeetingNotStarted(props: inferSSRProps<typeof getServerS
</div> </div>
<div className="mt-5 text-center sm:mt-6"> <div className="mt-5 text-center sm:mt-6">
<div className="mt-5"> <div className="mt-5">
<Button data-testid="return-home" href="/event-types" EndIcon={Icon.FiArrowRight}> <Button data-testid="return-home" href="/event-types" EndIcon={FiArrowRight}>
{t("go_back")} {t("go_back")}
</Button> </Button>
</div> </div>
+4 -3
View File
@@ -1,5 +1,6 @@
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, HeadSeo } from "@calcom/ui"; import { Button, HeadSeo } from "@calcom/ui";
import { FiX, FiArrowRight } from "@calcom/ui/components/icon";
export default function NoMeetingFound() { export default function NoMeetingFound() {
const { t } = useLocale(); const { t } = useLocale();
@@ -21,7 +22,7 @@ export default function NoMeetingFound() {
aria-labelledby="modal-headline"> aria-labelledby="modal-headline">
<div> <div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
<Icon.FiX className="h-6 w-6 text-red-600" /> <FiX className="h-6 w-6 text-red-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
@@ -34,7 +35,7 @@ export default function NoMeetingFound() {
</div> </div>
<div className="mt-5 text-center sm:mt-6"> <div className="mt-5 text-center sm:mt-6">
<div className="mt-5"> <div className="mt-5">
<Button data-testid="return-home" href="/event-types" EndIcon={Icon.FiArrowRight}> <Button data-testid="return-home" href="/event-types" EndIcon={FiArrowRight}>
{t("go_back_home")} {t("go_back_home")}
</Button> </Button>
</div> </div>
+26 -1
View File
@@ -1,6 +1,6 @@
import type { Page, WorkerInfo } from "@playwright/test"; import type { Page, WorkerInfo } from "@playwright/test";
import type Prisma from "@prisma/client"; import type Prisma from "@prisma/client";
import { Prisma as PrismaType } from "@prisma/client"; import { Prisma as PrismaType, MembershipRole } from "@prisma/client";
import { hash } from "bcryptjs"; import { hash } from "bcryptjs";
import dayjs from "@calcom/dayjs"; import dayjs from "@calcom/dayjs";
@@ -34,6 +34,27 @@ const seededForm = {
type UserWithIncludes = PrismaType.UserGetPayload<typeof userWithEventTypes>; type UserWithIncludes = PrismaType.UserGetPayload<typeof userWithEventTypes>;
const createTeamAndAddUser = async ({ user }: { user: { id: number; role?: MembershipRole } }) => {
const team = await prisma.team.create({
data: {
name: "",
slug: `team-${Date.now()}`,
},
});
if (!team) {
return;
}
const { role = MembershipRole.OWNER, id: userId } = user;
await prisma.membership.create({
data: {
teamId: team.id,
userId,
role: role,
},
});
};
// creates a user fixture instance and stores the collection // creates a user fixture instance and stores the collection
export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => { export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
const store = { users: [], page } as { users: UserFixture[]; page: typeof page }; const store = { users: [], page } as { users: UserFixture[]; page: typeof page };
@@ -42,6 +63,7 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
opts?: CustomUserOpts | null, opts?: CustomUserOpts | null,
scenario: { scenario: {
seedRoutingForms?: boolean; seedRoutingForms?: boolean;
hasTeam?: true;
} = {} } = {}
) => { ) => {
const _user = await prisma.user.create({ const _user = await prisma.user.create({
@@ -193,6 +215,9 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
where: { id: _user.id }, where: { id: _user.id },
include: userIncludes, include: userIncludes,
}); });
if (scenario.hasTeam) {
await createTeamAndAddUser({ user: { id: user.id, role: "OWNER" } });
}
const userFixture = createUserFixture(user, store.page!); const userFixture = createUserFixture(user, store.page!);
store.users.push(userFixture); store.users.push(userFixture);
return userFixture; return userFixture;
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

+10 -1
View File
@@ -24,6 +24,7 @@
"rejection_confirmation": "Reject the booking", "rejection_confirmation": "Reject the booking",
"manage_this_event": "Manage this event", "manage_this_event": "Manage this event",
"invite_team_member": "Invite team member", "invite_team_member": "Invite team member",
"invite_team_notifcation_badge":"Inv.",
"your_event_has_been_scheduled": "Your event has been scheduled", "your_event_has_been_scheduled": "Your event has been scheduled",
"your_event_has_been_scheduled_recurring": "Your recurring event has been scheduled", "your_event_has_been_scheduled_recurring": "Your recurring event has been scheduled",
"accept_our_license": "Accept our license by changing the .env variable <1>NEXT_PUBLIC_LICENSE_CONSENT</1> to '{{agree}}'.", "accept_our_license": "Accept our license by changing the .env variable <1>NEXT_PUBLIC_LICENSE_CONSENT</1> to '{{agree}}'.",
@@ -1238,6 +1239,7 @@
"to": "To", "to": "To",
"workflow_turned_on_successfully": "{{workflowName}} workflow turned {{offOn}} successfully", "workflow_turned_on_successfully": "{{workflowName}} workflow turned {{offOn}} successfully",
"download_responses": "Download Responses", "download_responses": "Download Responses",
"download_responses_description": "Download all responses to your form in CSV format.",
"download": "Download", "download": "Download",
"create_your_first_form": "Create your first form", "create_your_first_form": "Create your first form",
"create_your_first_form_description": "With Routing Forms you can ask qualifying questions and route to the correct person or event type.", "create_your_first_form_description": "With Routing Forms you can ask qualifying questions and route to the correct person or event type.",
@@ -1280,6 +1282,8 @@
"routing_forms_send_email_owner": "Send Email to Owner", "routing_forms_send_email_owner": "Send Email to Owner",
"routing_forms_send_email_owner_description": "Sends an email to the owner when the form is submitted", "routing_forms_send_email_owner_description": "Sends an email to the owner when the form is submitted",
"add_new_form": "Add new form", "add_new_form": "Add new form",
"create_your_first_route": "Create your first route",
"route_to_the_right_person": "Route to the right person based on the answers to your form",
"form_description": "Create your form to route a booker", "form_description": "Create your form to route a booker",
"copy_link_to_form": "Copy link to form", "copy_link_to_form": "Copy link to form",
"theme": "Theme", "theme": "Theme",
@@ -1310,6 +1314,7 @@
"password_reset_leading": "If you don't receive an email soon, check that the email address you entered is correct, check your spam folder or reach out to support if the issue persists.", "password_reset_leading": "If you don't receive an email soon, check that the email address you entered is correct, check your spam folder or reach out to support if the issue persists.",
"password_updated": "Password updated!", "password_updated": "Password updated!",
"pending_payment": "Pending payment", "pending_payment": "Pending payment",
"pending_invites":"Pending Invites",
"confirmation_page_rainbow": "Token gate your event with tokens or NFTs on Ethereum, Polygon, and more.", "confirmation_page_rainbow": "Token gate your event with tokens or NFTs on Ethereum, Polygon, and more.",
"not_on_cal": "Not on {{appName}}", "not_on_cal": "Not on {{appName}}",
"no_calendar_installed": "No calendar installed", "no_calendar_installed": "No calendar installed",
@@ -1514,5 +1519,9 @@
"install_google_meet": "Install Google Meet", "install_google_meet": "Install Google Meet",
"install_google_calendar": "Install Google Calendar", "install_google_calendar": "Install Google Calendar",
"sender_name": "Sender name", "sender_name": "Sender name",
"no_recordings_found": "No recordings found" "no_recordings_found": "No recordings found",
"reporting": "Reporting",
"reporting_feature": "See all incoming from data and download it as a CSV",
"teams_plan_required": "Teams plan required",
"routing_forms_are_a_great_way": "Routing forms are a great way to route your incoming leads to the right person. Upgrade to a Teams plan to access this feature."
} }
+2 -2
View File
@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# If there's a `.gitmodule` file skip this script # Skip if `.gitmodules` exists
[ -f .gitmodules ] && { [ -f .gitmodules ] && {
echo ".gitmodules already initializied" echo ".gitmodules already initialized"
exit 0 exit 0
} }
+4 -2
View File
@@ -5,11 +5,13 @@ if [ $# -eq 0 ]; then
echo "Usage: git-setup.sh <api,console,website>" echo "Usage: git-setup.sh <api,console,website>"
exit 1 exit 1
fi fi
# Get remote url to support either https or ssh
remote_url=$(echo $(git config --get remote.origin.url) | sed 's![^/]*$!!')
# Loop through the requested modules # Loop through the requested modules
for module in "$@"; do for module in "$@"; do
echo "Setting up '$module' module..." echo "Setting up '$module' module..."
# Set the project git URL # Set the project git URL
project=$(echo "git@github.com:calcom/$module.git") project=$remote_url$module.git
# Check if we have access to the module # Check if we have access to the module
if [ "$(git ls-remote "$project" 2>/dev/null)" ]; then if [ "$(git ls-remote "$project" 2>/dev/null)" ]; then
echo "You have access to '${module}'" echo "You have access to '${module}'"
@@ -18,7 +20,7 @@ for module in "$@"; do
# Prevents duplicate entries # Prevents duplicate entries
git config -f .gitmodules --unset-all "submodule.apps/$module.branch" git config -f .gitmodules --unset-all "submodule.apps/$module.branch"
# Add the submodule # Add the submodule
git submodule add --force "git@github.com:calcom/$module.git" "apps/$module" git submodule add --force $project "apps/$module"
# Set the default branch to main # Set the default branch to main
git config -f .gitmodules --add "submodule.apps/$module.branch" main git config -f .gitmodules --add "submodule.apps/$module.branch" main
# Adding the subdmoule ignores the `.gitignore` so a reset is needed # Adding the subdmoule ignores the `.gitignore` so a reset is needed
@@ -16,7 +16,11 @@ export const EventTypeAppCard = (props: {
return ( return (
<ErrorBoundary message={`There is some problem with ${app.name} App`}> <ErrorBoundary message={`There is some problem with ${app.name} App`}>
<EventTypeAppContext.Provider value={[getAppData, setAppData]}> <EventTypeAppContext.Provider value={[getAppData, setAppData]}>
<DynamicComponent slug={app.slug} componentMap={EventTypeAddonMap} {...props} /> <DynamicComponent
slug={app.slug === "stripe" ? "stripepayment" : app.slug}
componentMap={EventTypeAddonMap}
{...props}
/>
</EventTypeAppContext.Provider> </EventTypeAppContext.Provider>
</ErrorBoundary> </ErrorBoundary>
); );
@@ -2,7 +2,8 @@ import { classNames } from "@calcom/lib";
import useApp from "@calcom/lib/hooks/useApp"; import useApp from "@calcom/lib/hooks/useApp";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, Icon, showToast } from "@calcom/ui"; import { Button, showToast } from "@calcom/ui";
import { FiPlus } from "@calcom/ui/components/icon";
import useAddAppMutation from "../_utils/useAddAppMutation"; import useAddAppMutation from "../_utils/useAddAppMutation";
import { InstallAppButton } from "../components"; import { InstallAppButton } from "../components";
@@ -62,7 +63,7 @@ export default function OmniInstallAppButton({
loading={mutation.isLoading} loading={mutation.isLoading}
color="secondary" color="secondary"
className="[@media(max-width:260px)]:w-full [@media(max-width:260px)]:justify-center" className="[@media(max-width:260px)]:w-full [@media(max-width:260px)]:justify-center"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
{...props}> {...props}>
{t("install")} {t("install")}
</Button> </Button>
@@ -1,5 +1,5 @@
import { WEBAPP_URL } from "@calcom/lib/constants"; import { WEBAPP_URL } from "@calcom/lib/constants";
import { Icon } from "@calcom/ui"; import { FiCalendar, FiVideo, FiCreditCard, FiShare2, FiBarChart, FiGrid } from "@calcom/ui/components/icon";
function getHref(baseURL: string, category: string, useQueryParam: boolean) { function getHref(baseURL: string, category: string, useQueryParam: boolean) {
const baseUrlParsed = new URL(baseURL, WEBAPP_URL); const baseUrlParsed = new URL(baseURL, WEBAPP_URL);
@@ -12,37 +12,37 @@ const getAppCategories = (baseURL: string, useQueryParam: boolean) => {
{ {
name: "calendar", name: "calendar",
href: getHref(baseURL, "calendar", useQueryParam), href: getHref(baseURL, "calendar", useQueryParam),
icon: Icon.FiCalendar, icon: FiCalendar,
}, },
{ {
name: "conferencing", name: "conferencing",
href: getHref(baseURL, "conferencing", useQueryParam), href: getHref(baseURL, "conferencing", useQueryParam),
icon: Icon.FiVideo, icon: FiVideo,
}, },
{ {
name: "payment", name: "payment",
href: getHref(baseURL, "payment", useQueryParam), href: getHref(baseURL, "payment", useQueryParam),
icon: Icon.FiCreditCard, icon: FiCreditCard,
}, },
{ {
name: "automation", name: "automation",
href: getHref(baseURL, "automation", useQueryParam), href: getHref(baseURL, "automation", useQueryParam),
icon: Icon.FiShare2, icon: FiShare2,
}, },
{ {
name: "analytics", name: "analytics",
href: getHref(baseURL, "analytics", useQueryParam), href: getHref(baseURL, "analytics", useQueryParam),
icon: Icon.FiBarChart, icon: FiBarChart,
}, },
{ {
name: "web3", name: "web3",
href: getHref(baseURL, "web3", useQueryParam), href: getHref(baseURL, "web3", useQueryParam),
icon: Icon.FiBarChart, icon: FiBarChart,
}, },
{ {
name: "other", name: "other",
href: getHref(baseURL, "other", useQueryParam), href: getHref(baseURL, "other", useQueryParam),
icon: Icon.FiGrid, icon: FiGrid,
}, },
]; ];
}; };
@@ -6,7 +6,8 @@ import { Toaster } from "react-hot-toast";
import z from "zod"; import z from "zod";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Form, showToast, TextField, Icon } from "@calcom/ui"; import { Button, Form, showToast, TextField } from "@calcom/ui";
import { FiCheck, FiX } from "@calcom/ui/components/icon";
const formSchema = z.object({ const formSchema = z.object({
api_key: z.string(), api_key: z.string(),
@@ -106,7 +107,7 @@ export default function CloseComSetup() {
type="submit" type="submit"
loading={testLoading} loading={testLoading}
disabled={testPassed === true} disabled={testPassed === true}
StartIcon={testPassed !== undefined ? (testPassed ? Icon.FiCheck : Icon.FiX) : undefined} StartIcon={testPassed !== undefined ? (testPassed ? FiCheck : FiX) : undefined}
className={ className={
testPassed !== undefined testPassed !== undefined
? testPassed ? testPassed
@@ -22,13 +22,13 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
Form, Form,
Icon,
showToast, showToast,
Switch, Switch,
TextAreaField, TextAreaField,
TextField, TextField,
SettingsToggle, SettingsToggle,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiMoreHorizontal } from "@calcom/ui/components/icon";
import { EmbedButton, EmbedDialog } from "@components/Embed"; import { EmbedButton, EmbedDialog } from "@components/Embed";
@@ -162,7 +162,7 @@ export const FormActionsDropdown = ({ form, children }: { form: RoutingForm; chi
variant="icon" variant="icon"
color="secondary" color="secondary"
className={classNames("radix-state-open:rounded-r-md", disabled && "opacity-30")} className={classNames("radix-state-open:rounded-r-md", disabled && "opacity-30")}
StartIcon={Icon.FiMoreHorizontal} StartIcon={FiMoreHorizontal}
/> />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent>{children}</DropdownMenuContent> <DropdownMenuContent>{children}</DropdownMenuContent>
@@ -25,7 +25,6 @@ import {
DialogHeader, DialogHeader,
DropdownMenuSeparator, DropdownMenuSeparator,
Form, Form,
Icon,
Meta, Meta,
SettingsToggle, SettingsToggle,
showToast, showToast,
@@ -34,6 +33,7 @@ import {
Tooltip, Tooltip,
VerticalDivider, VerticalDivider,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiExternalLink, FiLink, FiDownload, FiCode, FiTrash } from "@calcom/ui/components/icon";
import { RoutingPages } from "../lib/RoutingPages"; import { RoutingPages } from "../lib/RoutingPages";
import { getSerializableForm } from "../lib/getSerializableForm"; import { getSerializableForm } from "../lib/getSerializableForm";
@@ -77,7 +77,7 @@ const Actions = ({
type="button" type="button"
rel="noreferrer" rel="noreferrer"
action="preview" action="preview"
StartIcon={Icon.FiExternalLink} StartIcon={FiExternalLink}
/> />
</Tooltip> </Tooltip>
<FormAction <FormAction
@@ -86,7 +86,7 @@ const Actions = ({
color="secondary" color="secondary"
variant="icon" variant="icon"
type="button" type="button"
StartIcon={Icon.FiLink} StartIcon={FiLink}
tooltip={t("copy_link_to_form")} tooltip={t("copy_link_to_form")}
/> />
@@ -98,7 +98,7 @@ const Actions = ({
color="secondary" color="secondary"
variant="icon" variant="icon"
type="button" type="button"
StartIcon={Icon.FiDownload} StartIcon={FiDownload}
/> />
</Tooltip> </Tooltip>
<FormAction <FormAction
@@ -106,7 +106,7 @@ const Actions = ({
action="embed" action="embed"
color="secondary" color="secondary"
variant="icon" variant="icon"
StartIcon={Icon.FiCode} StartIcon={FiCode}
tooltip={t("embed")} tooltip={t("embed")}
/> />
<DropdownMenuSeparator /> <DropdownMenuSeparator />
@@ -115,7 +115,7 @@ const Actions = ({
action="_delete" action="_delete"
// className="mr-3" // className="mr-3"
variant="icon" variant="icon"
StartIcon={Icon.FiTrash} StartIcon={FiTrash}
color="secondary" color="secondary"
type="button" type="button"
tooltip={t("delete")} tooltip={t("delete")}
@@ -128,7 +128,7 @@ const Actions = ({
action="copyRedirectUrl" action="copyRedirectUrl"
color="minimal" color="minimal"
type="button" type="button"
StartIcon={Icon.FiLink}> StartIcon={FiLink}>
{t("Copy Typeform Redirect Url")} {t("Copy Typeform Redirect Url")}
</FormAction> </FormAction>
</FormActionsDropdown> </FormActionsDropdown>
@@ -144,7 +144,7 @@ const Actions = ({
type="button" type="button"
rel="noreferrer" rel="noreferrer"
action="preview" action="preview"
StartIcon={Icon.FiExternalLink}> StartIcon={FiExternalLink}>
{t("preview")} {t("preview")}
</FormAction> </FormAction>
<FormAction <FormAction
@@ -153,7 +153,7 @@ const Actions = ({
routingForm={form} routingForm={form}
color="minimal" color="minimal"
type="button" type="button"
StartIcon={Icon.FiLink}> StartIcon={FiLink}>
{t("copy_link_to_form")} {t("copy_link_to_form")}
</FormAction> </FormAction>
<FormAction <FormAction
@@ -162,7 +162,7 @@ const Actions = ({
className="w-full" className="w-full"
color="minimal" color="minimal"
type="button" type="button"
StartIcon={Icon.FiDownload}> StartIcon={FiDownload}>
{t("download_responses")} {t("download_responses")}
</FormAction> </FormAction>
<FormAction <FormAction
@@ -171,7 +171,7 @@ const Actions = ({
color="minimal" color="minimal"
type="button" type="button"
className="w-full" className="w-full"
StartIcon={Icon.FiCode}> StartIcon={FiCode}>
{t("embed")} {t("embed")}
</FormAction> </FormAction>
{typeformApp ? ( {typeformApp ? (
@@ -181,7 +181,7 @@ const Actions = ({
action="copyRedirectUrl" action="copyRedirectUrl"
color="minimal" color="minimal"
type="button" type="button"
StartIcon={Icon.FiLink}> StartIcon={FiLink}>
{t("Copy Typeform Redirect Url")} {t("Copy Typeform Redirect Url")}
</FormAction> </FormAction>
) : null} ) : null}
@@ -192,7 +192,7 @@ const Actions = ({
className="w-full" className="w-full"
type="button" type="button"
color="destructive" color="destructive"
StartIcon={Icon.FiTrash}> StartIcon={FiTrash}>
{t("delete")} {t("delete")}
</FormAction> </FormAction>
</FormActionsDropdown> </FormActionsDropdown>
@@ -10,7 +10,8 @@ import {
TextWidgetProps, TextWidgetProps,
} from "react-awesome-query-builder"; } from "react-awesome-query-builder";
import { Button as CalButton, Icon, SelectWithValidation as Select, TextArea, TextField } from "@calcom/ui"; import { Button as CalButton, SelectWithValidation as Select, TextArea, TextField } from "@calcom/ui";
import { FiTrash, FiPlus } from "@calcom/ui/components/icon";
// import { mapListValues } from "../../../../utils/stuff"; // import { mapListValues } from "../../../../utils/stuff";
@@ -152,7 +153,7 @@ function Button({ config, type, label, onClick, readonly }: ButtonProps) {
if (type === "delRule" || type == "delGroup") { if (type === "delRule" || type == "delGroup") {
return ( return (
<button className="ml-5"> <button className="ml-5">
<Icon.FiTrash className="m-0 h-4 w-4 text-gray-500" onClick={onClick} /> <FiTrash className="m-0 h-4 w-4 text-gray-500" onClick={onClick} />
</button> </button>
); );
} }
@@ -166,7 +167,7 @@ function Button({ config, type, label, onClick, readonly }: ButtonProps) {
} }
return ( return (
<CalButton <CalButton
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
data-testid={dataTestId} data-testid={dataTestId}
type="button" type="button"
color="secondary" color="secondary"
@@ -10,11 +10,11 @@ import {
Button, Button,
EmptyScreen, EmptyScreen,
FormCard, FormCard,
Icon,
SelectField, SelectField,
TextAreaField, TextAreaField,
TextField, TextField,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiPlus, FiFileText } from "@calcom/ui/components/icon";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -286,7 +286,7 @@ const FormEdit = ({
<Button <Button
data-testid="add-field" data-testid="add-field"
type="button" type="button"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
color="secondary" color="secondary"
onClick={addField}> onClick={addField}>
Add Field Add Field
@@ -298,7 +298,7 @@ const FormEdit = ({
) : ( ) : (
<div className="w-full"> <div className="w-full">
<EmptyScreen <EmptyScreen
Icon={Icon.FiFileText} Icon={FiFileText}
headline="Create your first field" headline="Create your first field"
description="Fields are the form fields that the booker would see." description="Fields are the form fields that the booker would see."
buttonRaw={ buttonRaw={
@@ -1,8 +1,12 @@
// TODO: i18n // TODO: i18n
import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import SkeletonLoaderTeamList from "@calcom/features/ee/teams/components/SkeletonloaderTeamList";
import Shell, { ShellMain } from "@calcom/features/shell/Shell"; import Shell, { ShellMain } from "@calcom/features/shell/Shell";
import { UpgradeTip } from "@calcom/features/tips";
import { WEBAPP_URL } from "@calcom/lib/constants";
import useApp from "@calcom/lib/hooks/useApp"; import useApp from "@calcom/lib/hooks/useApp";
import { useHasTeamPlan } from "@calcom/lib/hooks/useHasTeamPlan";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { AppGetServerSidePropsContext, AppPrisma, AppUser } from "@calcom/types/AppGetServerSideProps"; import { AppGetServerSidePropsContext, AppPrisma, AppUser } from "@calcom/types/AppGetServerSideProps";
@@ -11,11 +15,29 @@ import {
ButtonGroup, ButtonGroup,
DropdownMenuSeparator, DropdownMenuSeparator,
EmptyScreen, EmptyScreen,
Icon,
List, List,
ListLinkItem, ListLinkItem,
Tooltip, Tooltip,
Button,
} from "@calcom/ui"; } from "@calcom/ui";
import {
FiPlus,
FiGitMerge,
FiExternalLink,
FiLink,
FiEdit,
FiDownload,
FiCode,
FiCopy,
FiTrash,
FiMenu,
FiMessageCircle,
FiFileText,
FiShuffle,
FiBarChart,
FiCheckCircle,
FiMail,
} from "@calcom/ui/components/icon";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -27,156 +49,218 @@ export default function RoutingForms({
appUrl, appUrl,
}: inferSSRProps<typeof getServerSideProps> & { appUrl: string }) { }: inferSSRProps<typeof getServerSideProps> & { appUrl: string }) {
const { t } = useLocale(); const { t } = useLocale();
const { data: forms } = trpc.viewer.appRoutingForms.forms.useQuery(undefined, { const { hasTeamPlan } = useHasTeamPlan();
const { data: forms, isLoading } = trpc.viewer.appRoutingForms.forms.useQuery(undefined, {
initialData: forms_, initialData: forms_,
}); });
const { data: typeformApp } = useApp("typeform"); const { data: typeformApp } = useApp("typeform");
const features = [
{
icon: <FiFileText className="h-5 w-5 text-orange-500" />,
title: t("create_your_first_form"),
description: t("create_your_first_form_description"),
},
{
icon: <FiShuffle className="h-5 w-5 text-lime-500" />,
title: t("create_your_first_route"),
description: t("route_to_the_right_person"),
},
{
icon: <FiBarChart className="h-5 w-5 text-blue-500" />,
title: t("reporting"),
description: t("reporting_feature"),
},
{
icon: <FiCheckCircle className="h-5 w-5 text-teal-500" />,
title: t("test_routing_form"),
description: t("test_preview_description"),
},
{
icon: <FiMail className="h-5 w-5 text-yellow-500" />,
title: t("routing_forms_send_email_owner"),
description: t("routing_forms_send_email_owner_description"),
},
{
icon: <FiDownload className="h-5 w-5 text-violet-500" />,
title: t("download_responses"),
description: t("download_responses_description"),
},
];
function NewFormButton() { function NewFormButton() {
return ( return (
<FormAction <FormAction
variant="fab" variant="fab"
routingForm={null} routingForm={null}
data-testid="new-routing-form" data-testid="new-routing-form"
StartIcon={Icon.FiPlus} StartIcon={FiPlus}
action="create"> action="create">
{t("new")} {t("new")}
</FormAction> </FormAction>
); );
} }
return ( return (
<ShellMain heading="Routing Forms" CTA={<NewFormButton />} subtitle={t("routing_forms_description")}> <ShellMain
<FormActionsProvider appUrl={appUrl}> heading="Routing Forms"
<div className="-mx-4 md:-mx-8"> CTA={hasTeamPlan && <NewFormButton />}
<div className="mb-10 w-full px-4 pb-2 sm:px-6 md:px-8"> subtitle={t("routing_forms_description")}>
{!forms?.length ? ( <UpgradeTip
<EmptyScreen dark
Icon={Icon.FiGitMerge} title={t("teams_plan_required")}
headline={t("create_your_first_form")} description={t("routing_forms_are_a_great_way")}
description={t("create_your_first_form_description")} features={features}
buttonRaw={<NewFormButton />} background="/routing-form-banner-background.jpg"
/> isParentLoading={isLoading && <SkeletonLoaderTeamList />}
) : null} buttons={
{forms?.length ? ( <div className="space-y-2 rtl:space-x-reverse sm:space-x-2">
<div className="mb-16 overflow-hidden bg-white"> <ButtonGroup>
<List data-testid="routing-forms-list"> <Button color="secondary" href={`${WEBAPP_URL}/settings/teams/new`}>
{forms.map((form, index) => { {t("upgrade")}
if (!form) { </Button>
return null; <Button
} color="minimal"
className="!bg-transparent text-white opacity-50 hover:opacity-100"
href="https://go.cal.com/teams-video"
target="_blank">
{t("learn_more")}
</Button>
</ButtonGroup>
</div>
}>
<FormActionsProvider appUrl={appUrl}>
<div className="-mx-4 md:-mx-8">
<div className="mb-10 w-full px-4 pb-2 sm:px-6 md:px-8">
{!forms?.length ? (
<EmptyScreen
Icon={FiGitMerge}
headline={t("create_your_first_form")}
description={t("create_your_first_form_description")}
buttonRaw={<NewFormButton />}
/>
) : null}
{forms?.length ? (
<div className="mb-16 overflow-hidden bg-white">
<List data-testid="routing-forms-list">
{forms.map((form, index) => {
if (!form) {
return null;
}
const description = form.description || ""; const description = form.description || "";
const disabled = form.disabled; const disabled = form.disabled;
form.routes = form.routes || []; form.routes = form.routes || [];
const fields = form.fields || []; const fields = form.fields || [];
return ( return (
<ListLinkItem <ListLinkItem
key={index} key={index}
href={appUrl + "/form-edit/" + form.id} href={appUrl + "/form-edit/" + form.id}
heading={form.name} heading={form.name}
disabled={disabled} disabled={disabled}
subHeading={description} subHeading={description}
actions={ actions={
<> <>
<FormAction className="self-center" action="toggle" routingForm={form} /> <FormAction className="self-center" action="toggle" routingForm={form} />
<ButtonGroup combined> <ButtonGroup combined>
<Tooltip content={t("preview")}> <Tooltip content={t("preview")}>
<FormAction
action="preview"
routingForm={form}
target="_blank"
StartIcon={FiExternalLink}
color="secondary"
variant="icon"
disabled={disabled}
/>
</Tooltip>
<FormAction <FormAction
action="preview"
routingForm={form} routingForm={form}
target="_blank" action="copyLink"
StartIcon={Icon.FiExternalLink}
color="secondary" color="secondary"
variant="icon" variant="icon"
StartIcon={FiLink}
disabled={disabled} disabled={disabled}
tooltip={t("copy_link_to_form")}
/> />
</Tooltip> <FormActionsDropdown form={form}>
<FormAction
routingForm={form}
action="copyLink"
color="secondary"
variant="icon"
StartIcon={Icon.FiLink}
disabled={disabled}
tooltip={t("copy_link_to_form")}
/>
<FormActionsDropdown form={form}>
<FormAction
action="edit"
routingForm={form}
color="minimal"
className="!flex"
StartIcon={Icon.FiEdit}>
{t("edit")}
</FormAction>
<FormAction
action="download"
routingForm={form}
color="minimal"
StartIcon={Icon.FiDownload}>
{t("download_responses")}
</FormAction>
<FormAction
action="embed"
routingForm={form}
color="minimal"
className="w-full"
StartIcon={Icon.FiCode}>
{t("embed")}
</FormAction>
<FormAction
action="duplicate"
routingForm={form}
color="minimal"
className="w-full"
StartIcon={Icon.FiCopy}>
{t("duplicate")}
</FormAction>
{typeformApp?.isInstalled ? (
<FormAction <FormAction
data-testid="copy-redirect-url" action="edit"
routingForm={form} routingForm={form}
action="copyRedirectUrl"
color="minimal" color="minimal"
type="button" className="!flex"
StartIcon={Icon.FiLink}> StartIcon={FiEdit}>
{t("Copy Typeform Redirect Url")} {t("edit")}
</FormAction> </FormAction>
) : null} <FormAction
<DropdownMenuSeparator /> action="download"
<FormAction routingForm={form}
action="_delete" color="minimal"
routingForm={form} StartIcon={FiDownload}>
color="destructive" {t("download_responses")}
className="w-full" </FormAction>
StartIcon={Icon.FiTrash}> <FormAction
{t("delete")} action="embed"
</FormAction> routingForm={form}
</FormActionsDropdown> color="minimal"
</ButtonGroup> className="w-full"
</> StartIcon={FiCode}>
}> {t("embed")}
<div className="flex flex-wrap gap-1"> </FormAction>
<Badge variant="gray" StartIcon={Icon.FiMenu}> <FormAction
{fields.length} {fields.length === 1 ? "field" : "fields"} action="duplicate"
</Badge> routingForm={form}
<Badge variant="gray" StartIcon={Icon.FiGitMerge}> color="minimal"
{form.routes.length} {form.routes.length === 1 ? "route" : "routes"} className="w-full"
</Badge> StartIcon={FiCopy}>
<Badge variant="gray" StartIcon={Icon.FiMessageCircle}> {t("duplicate")}
{form._count.responses} {form._count.responses === 1 ? "response" : "responses"} </FormAction>
</Badge> {typeformApp?.isInstalled ? (
</div> <FormAction
</ListLinkItem> data-testid="copy-redirect-url"
); routingForm={form}
})} action="copyRedirectUrl"
</List> color="minimal"
</div> type="button"
) : null} StartIcon={FiLink}>
{t("Copy Typeform Redirect Url")}
</FormAction>
) : null}
<DropdownMenuSeparator />
<FormAction
action="_delete"
routingForm={form}
color="destructive"
className="w-full"
StartIcon={FiTrash}>
{t("delete")}
</FormAction>
</FormActionsDropdown>
</ButtonGroup>
</>
}>
<div className="flex flex-wrap gap-1">
<Badge variant="gray" StartIcon={FiMenu}>
{fields.length} {fields.length === 1 ? "field" : "fields"}
</Badge>
<Badge variant="gray" StartIcon={FiGitMerge}>
{form.routes.length} {form.routes.length === 1 ? "route" : "routes"}
</Badge>
<Badge variant="gray" StartIcon={FiMessageCircle}>
{form._count.responses} {form._count.responses === 1 ? "response" : "responses"}
</Badge>
</div>
</ListLinkItem>
);
})}
</List>
</div>
) : null}
</div>
</div> </div>
</div> </FormActionsProvider>
</FormActionsProvider> </UpgradeTip>
</ShellMain> </ShellMain>
); );
} }
@@ -118,7 +118,12 @@ test.describe("Routing Forms", () => {
// TODO: How to install the app just once? // TODO: How to install the app just once?
test.beforeEach(async ({ page, users }) => { test.beforeEach(async ({ page, users }) => {
const user = await users.create({ username: "routing-forms" }); const user = await users.create(
{ username: "routing-forms" },
{
hasTeam: true,
}
);
await user.login(); await user.login();
// Install app // Install app
await page.goto(`/apps/routing-forms`); await page.goto(`/apps/routing-forms`);
@@ -148,7 +153,10 @@ test.describe("Routing Forms", () => {
users: Fixtures["users"]; users: Fixtures["users"];
page: Page; page: Page;
}) { }) {
const user = await users.create({ username: "routing-forms" }, { seedRoutingForms: true }); const user = await users.create(
{ username: "routing-forms" },
{ seedRoutingForms: true, hasTeam: true }
);
await user.login(); await user.login();
// Install app // Install app
await page.goto(`/apps/routing-forms`); await page.goto(`/apps/routing-forms`);
+12 -10
View File
@@ -12,16 +12,18 @@
"email": "support@cal.com", "email": "support@cal.com",
"description": "Google Analytics is a web analytics service offered by Google that tracks and reports website traffic, currently as a platform inside the Google Marketing Platform brand.", "description": "Google Analytics is a web analytics service offered by Google that tracks and reports website traffic, currently as a platform inside the Google Marketing Platform brand.",
"extendsFeature": "EventType", "extendsFeature": "EventType",
"tag": { "appData": {
"scripts": [ "tag": {
{ "scripts": [
"src": "https://www.googletagmanager.com/gtag/js?id={TRACKING_ID}", {
"attrs": {} "src": "https://www.googletagmanager.com/gtag/js?id={TRACKING_ID}",
}, "attrs": {}
{ },
"content": "window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '{TRACKING_ID}');" {
} "content": "window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '{TRACKING_ID}');"
] }
]
}
}, },
"__createdUsingCli": true "__createdUsingCli": true
} }
@@ -4,7 +4,8 @@ import Link from "next/link";
import { CAL_URL } from "@calcom/lib/constants"; import { CAL_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc"; import { trpc } from "@calcom/trpc";
import { Icon, SkeletonText } from "@calcom/ui"; import { SkeletonText } from "@calcom/ui";
import { FiAlertCircle } from "@calcom/ui/components/icon";
const ExistingGoogleCal = () => { const ExistingGoogleCal = () => {
const { t } = useLocale(); const { t } = useLocale();
@@ -14,7 +15,7 @@ const ExistingGoogleCal = () => {
<div className="rounded-md bg-blue-100 py-3 px-4 text-blue-900"> <div className="rounded-md bg-blue-100 py-3 px-4 text-blue-900">
<div className="flex items-start space-x-2.5"> <div className="flex items-start space-x-2.5">
<div> <div>
<Icon.FiAlertCircle className="font-semibold" /> <FiAlertCircle className="font-semibold" />
</div> </div>
<div> <div>
<span className="font-semibold">{t("requires_google_calendar")}</span> <span className="font-semibold">{t("requires_google_calendar")}</span>
@@ -52,7 +52,7 @@ const o365Auth = async (credential: CredentialPayload) => {
if (!client_id) throw new HttpError({ statusCode: 400, message: "MS teams client_id missing." }); if (!client_id) throw new HttpError({ statusCode: 400, message: "MS teams client_id missing." });
if (!client_secret) throw new HttpError({ statusCode: 400, message: "MS teams client_secret missing." }); if (!client_secret) throw new HttpError({ statusCode: 400, message: "MS teams client_secret missing." });
const isExpired = (expiryDate: number) => expiryDate < Math.round(+new Date() / 1000); const isExpired = (expiryDate: number) => expiryDate < Math.round(+new Date());
const o365AuthCredentials = credential.key as unknown as O365AuthCredentials; const o365AuthCredentials = credential.key as unknown as O365AuthCredentials;
@@ -69,9 +69,10 @@ const o365Auth = async (credential: CredentialPayload) => {
}); });
const responseBody = await handleErrorsJson<ITokenResponse>(response); const responseBody = await handleErrorsJson<ITokenResponse>(response);
if (responseBody?.error) { if (responseBody?.error) {
console.error(responseBody); console.error(responseBody);
throw new HttpError({ statusCode: 500, message: "Error contacting MS Teams" }); throw new HttpError({ statusCode: 500, message: `Error contacting MS Teams: ${responseBody.error}` });
} }
// set expiry date as offset from current time. // set expiry date as offset from current time.
responseBody.expiry_date = Math.round(Date.now() + (responseBody?.expires_in || 0) * 1000); responseBody.expiry_date = Math.round(Date.now() + (responseBody?.expires_in || 0) * 1000);
@@ -93,9 +94,9 @@ const o365Auth = async (credential: CredentialPayload) => {
return { return {
getToken: () => getToken: () =>
!isExpired(o365AuthCredentials.expiry_date) isExpired(o365AuthCredentials.expiry_date)
? Promise.resolve(o365AuthCredentials.access_token) ? refreshAccessToken(o365AuthCredentials.refresh_token)
: refreshAccessToken(o365AuthCredentials.refresh_token), : Promise.resolve(o365AuthCredentials.access_token),
}; };
}; };
+10 -8
View File
@@ -11,15 +11,17 @@
"publisher": "Cal.com, Inc.", "publisher": "Cal.com, Inc.",
"email": "help@cal.com", "email": "help@cal.com",
"extendsFeature": "EventType", "extendsFeature": "EventType",
"tag": { "appData": {
"scripts": [ "tag": {
{ "scripts": [
"src": "https://plausible.io/js/script.js", {
"attrs": { "src": "https://plausible.io/js/script.js",
"data-domain": "{TRACKED_DOMAIN}" "attrs": {
"data-domain": "{TRACKED_DOMAIN}"
}
} }
} ]
] }
}, },
"description": "Simple, privacy-friendly Google Analytics alternative.", "description": "Simple, privacy-friendly Google Analytics alternative.",
"__createdUsingCli": true "__createdUsingCli": true
@@ -14,7 +14,8 @@ import { configureChains, createClient, useAccount, useSignMessage, WagmiConfig
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Icon, showToast, SkeletonText } from "@calcom/ui"; import { showToast, SkeletonText } from "@calcom/ui";
import { FiAlertTriangle, FiLoader } from "@calcom/ui/components/icon";
import { ETH_MESSAGE, getProviders, SUPPORTED_CHAINS } from "../utils/ethereum"; import { ETH_MESSAGE, getProviders, SUPPORTED_CHAINS } from "../utils/ethereum";
@@ -131,7 +132,7 @@ const BalanceCheck: React.FC<RainbowGateProps> = ({ chainId, setToken, tokenAddr
<> <>
{!balanceData.data.hasBalance && ( {!balanceData.data.hasBalance && (
<div className="mt-2 flex flex-row items-center"> <div className="mt-2 flex flex-row items-center">
<Icon.FiAlertTriangle className="h-5 w-5 text-red-600" /> <FiAlertTriangle className="h-5 w-5 text-red-600" />
<p className="ml-2 text-red-600"> <p className="ml-2 text-red-600">
<Trans i18nKey="rainbow_insufficient_balance" t={t}> <Trans i18nKey="rainbow_insufficient_balance" t={t}>
Your connected wallet doesn&apos;t contain enough {contractData.data.symbol}. Your connected wallet doesn&apos;t contain enough {contractData.data.symbol}.
@@ -142,7 +143,7 @@ const BalanceCheck: React.FC<RainbowGateProps> = ({ chainId, setToken, tokenAddr
{balanceData.data.hasBalance && isSignatureLoading && ( {balanceData.data.hasBalance && isSignatureLoading && (
<div className="mt-2 flex flex-row items-center"> <div className="mt-2 flex flex-row items-center">
<Icon.FiLoader className="h-5 w-5 text-green-600" /> <FiLoader className="h-5 w-5 text-green-600" />
<p className="ml-2 text-green-600">{t("rainbow_sign_message_request")}</p> <p className="ml-2 text-green-600">{t("rainbow_sign_message_request")}</p>
</div> </div>
)} )}
@@ -151,7 +152,7 @@ const BalanceCheck: React.FC<RainbowGateProps> = ({ chainId, setToken, tokenAddr
{isSignatureError && ( {isSignatureError && (
<div className="mt-2 flex flex-row items-center"> <div className="mt-2 flex flex-row items-center">
<Icon.FiAlertTriangle className="h-5 w-5 text-red-600" /> <FiAlertTriangle className="h-5 w-5 text-red-600" />
<p className="ml-2 text-red-600"> <p className="ml-2 text-red-600">
<Trans i18nKey="rainbow_signature_error" t={t}> <Trans i18nKey="rainbow_signature_error" t={t}>
{t("rainbow_signature_error")} {t("rainbow_signature_error")}
@@ -6,7 +6,8 @@ import { Toaster } from "react-hot-toast";
import z from "zod"; import z from "zod";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Form, Icon, showToast, TextField } from "@calcom/ui"; import { Button, Form, showToast, TextField } from "@calcom/ui";
import { FiCheck, FiX } from "@calcom/ui/components/icon";
const formSchema = z.object({ const formSchema = z.object({
api_key: z.string(), api_key: z.string(),
@@ -101,7 +102,7 @@ export default function SendgridSetup() {
type="submit" type="submit"
loading={testLoading} loading={testLoading}
disabled={testPassed === true} disabled={testPassed === true}
StartIcon={testPassed !== undefined ? (testPassed ? Icon.FiCheck : Icon.FiX) : undefined} StartIcon={testPassed !== undefined ? (testPassed ? FiCheck : FiX) : undefined}
className={ className={
testPassed !== undefined testPassed !== undefined
? testPassed ? testPassed
@@ -3,7 +3,7 @@ import { useState } from "react";
import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext"; import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext";
import AppCard from "@calcom/app-store/_components/AppCard"; import AppCard from "@calcom/app-store/_components/AppCard";
import type { EventTypeAppCardComponent } from "@calcom/app-store/types"; import type { EventTypeAppCardComponent } from "@calcom/app-store/types";
import { Icon } from "@calcom/ui"; import { FiSunrise, FiSunset } from "@calcom/ui/components/icon";
import { appDataSchema } from "../zod"; import { appDataSchema } from "../zod";
@@ -28,8 +28,8 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
switchChecked={enabled}> switchChecked={enabled}>
<div className="mt-2 text-sm"> <div className="mt-2 text-sm">
<div className="flex"> <div className="flex">
<span className="ltr:mr-2 rtl:ml-2">{isSunrise ? <Icon.FiSunrise /> : <Icon.FiSunset />}</span>I am <span className="ltr:mr-2 rtl:ml-2">{isSunrise ? <FiSunrise /> : <FiSunset />}</span>I am an AppCard
an AppCard for Event with Title: {eventType.title} for Event with Title: {eventType.title}
</div>{" "} </div>{" "}
<div className="mt-2"> <div className="mt-2">
Edit <span className="italic">packages/app-store/{app.slug}/EventTypeAppCardInterface.tsx</span> to Edit <span className="italic">packages/app-store/{app.slug}/EventTypeAppCardInterface.tsx</span> to
@@ -1,7 +1,8 @@
import Link from "next/link"; import Link from "next/link";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon } from "@calcom/ui"; import { Button } from "@calcom/ui";
import { FiExternalLink } from "@calcom/ui/components/icon";
export default function HowToUse() { export default function HowToUse() {
const { t } = useLocale(); const { t } = useLocale();
@@ -30,10 +31,7 @@ export default function HowToUse() {
href="/api/app-store/typeform/copy-typeform-redirect-url.png" href="/api/app-store/typeform/copy-typeform-redirect-url.png"
target="_blank" target="_blank"
className="inline-flex items-baseline text-base text-gray-500"> className="inline-flex items-baseline text-base text-gray-500">
<Icon.FiExternalLink <FiExternalLink className="h-4 w-4 text-gray-500 ltr:mr-2 rtl:ml-2" aria-hidden="true" />
className="h-4 w-4 text-gray-500 ltr:mr-2 rtl:ml-2"
aria-hidden="true"
/>
Click &quot;Copy Typeform Redirect URL&quot; Click &quot;Copy Typeform Redirect URL&quot;
</Link> </Link>
</li> </li>
@@ -44,10 +42,7 @@ export default function HowToUse() {
href="https://www.typeform.com/help/a/end-screens-and-redirects-360051791392/#h_01G0CFXF21W2EQ8PXKSB4KSC8P" href="https://www.typeform.com/help/a/end-screens-and-redirects-360051791392/#h_01G0CFXF21W2EQ8PXKSB4KSC8P"
target="_blank" target="_blank"
className="inline-flex items-baseline text-base text-gray-500"> className="inline-flex items-baseline text-base text-gray-500">
<Icon.FiExternalLink <FiExternalLink className="h-4 w-4 text-gray-500 ltr:mr-2 rtl:ml-2" aria-hidden="true" />
className="h-4 w-4 text-gray-500 ltr:mr-2 rtl:ml-2"
aria-hidden="true"
/>
Redirect to your typeform Redirect to your typeform
</Link> </Link>
</li> </li>
@@ -57,10 +52,7 @@ export default function HowToUse() {
href="https://www.typeform.com/help/a/use-recall-information-to-reference-typeform-answers-variables-and-more-360052320011/" href="https://www.typeform.com/help/a/use-recall-information-to-reference-typeform-answers-variables-and-more-360052320011/"
target="_blank" target="_blank"
className="inline-flex items-baseline text-base text-gray-500"> className="inline-flex items-baseline text-base text-gray-500">
<Icon.FiExternalLink <FiExternalLink className="h-4 w-4 text-gray-500 ltr:mr-2 rtl:ml-2" aria-hidden="true" />
className="h-4 w-4 text-gray-500 ltr:mr-2 rtl:ml-2"
aria-hidden="true"
/>
Recall Information in Typeform Recall Information in Typeform
</Link>{" "} </Link>{" "}
to add values to query params. to add values to query params.
@@ -8,7 +8,12 @@ import { CAL_URL } from "@calcom/lib/constants";
import { Fixtures, test } from "@calcom/web/playwright/lib/fixtures"; import { Fixtures, test } from "@calcom/web/playwright/lib/fixtures";
const installApps = async (page: Page, users: Fixtures["users"]) => { const installApps = async (page: Page, users: Fixtures["users"]) => {
const user = await users.create({ username: "routing-forms" }); const user = await users.create(
{ username: "routing-forms" },
{
hasTeam: true,
}
);
await user.login(); await user.login();
await page.goto(`/apps/routing-forms`); await page.goto(`/apps/routing-forms`);
await page.click('[data-testid="install-app-button"]'); await page.click('[data-testid="install-app-button"]');
@@ -5,7 +5,8 @@ import { Toaster } from "react-hot-toast";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, Icon, showToast, Tooltip } from "@calcom/ui"; import { Button, showToast, Tooltip } from "@calcom/ui";
import { ClipboardCopyIcon } from "@calcom/ui/components/icon";
export interface IZapierSetupProps { export interface IZapierSetupProps {
inviteLink: string; inviteLink: string;
@@ -75,7 +76,7 @@ export default function ZapierSetup(props: IZapierSetupProps) {
}} }}
type="button" type="button"
className="mt-4 text-base sm:mt-0 sm:rounded-l-none"> className="mt-4 text-base sm:mt-0 sm:rounded-l-none">
<Icon.ClipboardCopyIcon className="h-5 w-5 text-gray-100 ltr:mr-2 rtl:ml-2" /> <ClipboardCopyIcon className="h-5 w-5 text-gray-100 ltr:mr-2 rtl:ml-2" />
{t("copy")} {t("copy")}
</Button> </Button>
</Tooltip> </Tooltip>
+3 -3
View File
@@ -17,7 +17,6 @@ import {
Dialog, Dialog,
EmptyScreen, EmptyScreen,
Form, Form,
Icon,
showToast, showToast,
SkeletonButton, SkeletonButton,
SkeletonContainer, SkeletonContainer,
@@ -26,6 +25,7 @@ import {
TextField, TextField,
VerticalDivider, VerticalDivider,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiAlertCircle, FiEdit } from "@calcom/ui/components/icon";
const IntegrationContainer = ({ const IntegrationContainer = ({
app, app,
@@ -110,7 +110,7 @@ const IntegrationContainer = ({
variant="icon" variant="icon"
tooltip={t("edit_keys")} tooltip={t("edit_keys")}
onClick={() => setShowKeys(!showKeys)}> onClick={() => setShowKeys(!showKeys)}>
<Icon.FiEdit /> <FiEdit />
</Button> </Button>
</CollapsibleTrigger> </CollapsibleTrigger>
</> </>
@@ -224,7 +224,7 @@ const AdminAppsListContainer = () => {
if (!apps) { if (!apps) {
return ( return (
<EmptyScreen <EmptyScreen
Icon={Icon.FiAlertCircle} Icon={FiAlertCircle}
headline={t("no_available_apps")} headline={t("no_available_apps")}
description={t("no_available_apps_description")} description={t("no_available_apps_description")}
/> />
@@ -8,11 +8,11 @@ import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogTrigger, DialogTrigger,
Icon,
showToast, showToast,
DialogFooter, DialogFooter,
DialogClose, DialogClose,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiTrash, FiAlertCircle } from "@calcom/ui/components/icon";
export default function DisconnectIntegration({ export default function DisconnectIntegration({
credentialId, credentialId,
@@ -54,7 +54,7 @@ export default function DisconnectIntegration({
<DialogTrigger asChild> <DialogTrigger asChild>
<Button <Button
color={buttonProps?.color || "destructive"} color={buttonProps?.color || "destructive"}
StartIcon={trashIcon ? Icon.FiTrash : undefined} StartIcon={trashIcon ? FiTrash : undefined}
size="base" size="base"
variant={trashIcon && !label ? "icon" : "button"} variant={trashIcon && !label ? "icon" : "button"}
disabled={isGlobal} disabled={isGlobal}
@@ -66,7 +66,7 @@ export default function DisconnectIntegration({
title={t("remove_app")} title={t("remove_app")}
description={t("are_you_sure_you_want_to_remove_this_app")} description={t("are_you_sure_you_want_to_remove_this_app")}
type="confirmation" type="confirmation"
Icon={Icon.FiAlertCircle}> Icon={FiAlertCircle}>
<DialogFooter> <DialogFooter>
<DialogClose onClick={() => setModalOpen(false)} /> <DialogClose onClick={() => setModalOpen(false)} />
<DialogClose color="primary" onClick={() => mutation.mutate({ id: credentialId })}> <DialogClose color="primary" onClick={() => mutation.mutate({ id: credentialId })}>
+3 -2
View File
@@ -7,7 +7,8 @@ import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, Icon } from "@calcom/ui"; import { Button } from "@calcom/ui";
import { FiLock } from "@calcom/ui/components/icon";
interface Props { interface Props {
samlTenantID: string; samlTenantID: string;
@@ -35,7 +36,7 @@ export function SAMLLogin({ samlTenantID, samlProductID, setErrorMessage }: Prop
return ( return (
<Button <Button
StartIcon={Icon.FiLock} StartIcon={FiLock}
color="secondary" color="secondary"
data-testid="saml" data-testid="saml"
className="flex w-full justify-center" className="flex w-full justify-center"
@@ -1,6 +1,7 @@
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { AnimatedPopover, Avatar, Icon } from "@calcom/ui"; import { AnimatedPopover, Avatar } from "@calcom/ui";
import { FiUser } from "@calcom/ui/components/icon";
import { useFilterQuery } from "../lib/useFilterQuery"; import { useFilterQuery } from "../lib/useFilterQuery";
@@ -19,7 +20,7 @@ export const PeopleFilter = () => {
text={userNames && userNames.length > 0 ? `${userNames.join(", ")}` : t("all_users_filter_label")}> text={userNames && userNames.length > 0 ? `${userNames.join(", ")}` : t("all_users_filter_label")}>
<div className="item-center flex px-4 py-[6px] focus-within:bg-gray-100 hover:cursor-pointer hover:bg-gray-50"> <div className="item-center flex px-4 py-[6px] focus-within:bg-gray-100 hover:cursor-pointer hover:bg-gray-50">
<div className="flex h-6 w-6 items-center justify-center ltr:mr-2 rtl:ml-2"> <div className="flex h-6 w-6 items-center justify-center ltr:mr-2 rtl:ml-2">
<Icon.FiUser className="h-5 w-5" /> <FiUser className="h-5 w-5" />
</div> </div>
<label htmlFor="allUsers" className="mr-auto self-center truncate text-sm font-medium text-gray-700"> <label htmlFor="allUsers" className="mr-auto self-center truncate text-sm font-medium text-gray-700">
{t("all_users_filter_label")} {t("all_users_filter_label")}
@@ -2,7 +2,8 @@ import { useSession } from "next-auth/react";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { AnimatedPopover, Avatar, Icon } from "@calcom/ui"; import { AnimatedPopover, Avatar } from "@calcom/ui";
import { FiLayers, FiUser } from "@calcom/ui/components/icon";
import { useFilterQuery } from "../lib/useFilterQuery"; import { useFilterQuery } from "../lib/useFilterQuery";
@@ -22,7 +23,7 @@ export const TeamsMemberFilter = () => {
text={teamNames && teamNames.length > 0 ? `${teamNames.join(", ")}` : t("all_bookings_filter_label")}> text={teamNames && teamNames.length > 0 ? `${teamNames.join(", ")}` : t("all_bookings_filter_label")}>
<div className="item-center flex px-4 py-[6px] focus-within:bg-gray-100 hover:cursor-pointer hover:bg-gray-50"> <div className="item-center flex px-4 py-[6px] focus-within:bg-gray-100 hover:cursor-pointer hover:bg-gray-50">
<div className="flex h-6 w-6 items-center justify-center ltr:mr-2 rtl:ml-2"> <div className="flex h-6 w-6 items-center justify-center ltr:mr-2 rtl:ml-2">
<Icon.FiLayers className="h-5 w-5" /> <FiLayers className="h-5 w-5" />
</div> </div>
<label <label
htmlFor="allBookings" htmlFor="allBookings"
@@ -42,7 +43,7 @@ export const TeamsMemberFilter = () => {
</div> </div>
<div className="item-center flex px-4 py-[6px] focus-within:bg-gray-100 hover:cursor-pointer hover:bg-gray-50"> <div className="item-center flex px-4 py-[6px] focus-within:bg-gray-100 hover:cursor-pointer hover:bg-gray-50">
<div className="flex h-6 w-6 items-center justify-center ltr:mr-2 rtl:ml-2"> <div className="flex h-6 w-6 items-center justify-center ltr:mr-2 rtl:ml-2">
<Icon.FiUser className="h-5 w-5" /> <FiUser className="h-5 w-5" />
</div> </div>
<label <label
htmlFor="yourBookings" htmlFor="yourBookings"
+3 -2
View File
@@ -7,7 +7,8 @@ import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import useMediaQuery from "@calcom/lib/hooks/useMediaQuery"; import useMediaQuery from "@calcom/lib/hooks/useMediaQuery";
import { weekdayNames } from "@calcom/lib/weekday"; import { weekdayNames } from "@calcom/lib/weekday";
import { Button, Icon, SkeletonText } from "@calcom/ui"; import { Button, SkeletonText } from "@calcom/ui";
import { FiArrowRight } from "@calcom/ui/components/icon";
export type DatePickerProps = { export type DatePickerProps = {
/** which day of the week to render the calendar. Usually Sunday (=0) or Monday (=1) - default: Sunday */ /** which day of the week to render the calendar. Usually Sunday (=0) or Monday (=1) - default: Sunday */
@@ -83,7 +84,7 @@ const NoAvailabilityOverlay = ({
<h4 className="mb-4 font-medium text-gray-900 dark:text-white"> <h4 className="mb-4 font-medium text-gray-900 dark:text-white">
{t("no_availability_in_month", { month: month })} {t("no_availability_in_month", { month: month })}
</h4> </h4>
<Button onClick={nextMonthButton} color="primary" EndIcon={Icon.FiArrowRight}> <Button onClick={nextMonthButton} color="primary" EndIcon={FiArrowRight}>
{t("view_next_month")} {t("view_next_month")}
</Button> </Button>
</div> </div>
@@ -1,5 +1,6 @@
import dayjs from "@calcom/dayjs"; import dayjs from "@calcom/dayjs";
import { Icon, Button, ButtonGroup } from "@calcom/ui"; import { Button, ButtonGroup } from "@calcom/ui";
import { FiChevronLeft, FiChevronRight } from "@calcom/ui/components/icon";
import { useCalendarStore } from "../../state/store"; import { useCalendarStore } from "../../state/store";
@@ -29,7 +30,7 @@ export function SchedulerHeading() {
<ButtonGroup combined> <ButtonGroup combined>
{/* TODO: i18n label with correct view */} {/* TODO: i18n label with correct view */}
<Button <Button
StartIcon={Icon.FiChevronLeft} StartIcon={FiChevronLeft}
variant="icon" variant="icon"
color="secondary" color="secondary"
aria-label="Previous Week" aria-label="Previous Week"
@@ -38,7 +39,7 @@ export function SchedulerHeading() {
}} }}
/> />
<Button <Button
StartIcon={Icon.FiChevronRight} StartIcon={FiChevronRight}
variant="icon" variant="icon"
color="secondary" color="secondary"
aria-label="Next Week" aria-label="Next Week"
@@ -6,17 +6,8 @@ import { TApiKeys } from "@calcom/ee/api-keys/components/ApiKeyListItem";
import LicenseRequired from "@calcom/ee/common/components/v2/LicenseRequired"; import LicenseRequired from "@calcom/ee/common/components/v2/LicenseRequired";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { import { Button, DatePicker, DialogFooter, Form, showToast, Switch, TextField, Tooltip } from "@calcom/ui";
Button, import { ClipboardCopyIcon } from "@calcom/ui/components/icon";
Icon,
DatePicker,
DialogFooter,
Form,
showToast,
Switch,
TextField,
Tooltip,
} from "@calcom/ui";
export default function ApiKeyDialogForm({ export default function ApiKeyDialogForm({
defaultValues, defaultValues,
@@ -83,7 +74,7 @@ export default function ApiKeyDialogForm({
}} }}
type="button" type="button"
className="rounded-l-none py-[19px] text-base "> className="rounded-l-none py-[19px] text-base ">
<Icon.ClipboardCopyIcon className="h-5 w-5 text-gray-100 ltr:mr-2 rtl:ml-2" /> <ClipboardCopyIcon className="h-5 w-5 text-gray-100 ltr:mr-2 rtl:ml-2" />
{t("copy")} {t("copy")}
</Button> </Button>
</Tooltip> </Tooltip>
@@ -10,8 +10,8 @@ import {
DropdownMenuContent, DropdownMenuContent,
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
Icon,
} from "@calcom/ui"; } from "@calcom/ui";
import { FiMoreHorizontal, FiEdit2, FiTrash } from "@calcom/ui/components/icon";
export type TApiKeys = RouterOutputs["viewer"]["apiKeys"]["list"][number]; export type TApiKeys = RouterOutputs["viewer"]["apiKeys"]["list"][number];
@@ -66,12 +66,12 @@ const ApiKeyListItem = ({
<div> <div>
<Dropdown> <Dropdown>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<Button type="button" variant="icon" color="secondary" StartIcon={Icon.FiMoreHorizontal} /> <Button type="button" variant="icon" color="secondary" StartIcon={FiMoreHorizontal} />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
<DropdownMenuItem> <DropdownMenuItem>
<DropdownItem type="button" onClick={onEditClick} StartIcon={Icon.FiEdit2}> <DropdownItem type="button" onClick={onEditClick} StartIcon={FiEdit2}>
{t("edit") as string} {t("edit") as string}
</DropdownItem> </DropdownItem>
</DropdownMenuItem> </DropdownMenuItem>
@@ -83,7 +83,7 @@ const ApiKeyListItem = ({
id: apiKey.id, id: apiKey.id,
}) })
} }
StartIcon={Icon.FiTrash}> StartIcon={FiTrash}>
{t("delete") as string} {t("delete") as string}
</DropdownItem> </DropdownItem>
</DropdownMenuItem> </DropdownMenuItem>
@@ -9,7 +9,8 @@ import React, { AriaRole, ComponentType, Fragment } from "react";
import { APP_NAME, SUPPORT_MAIL_ADDRESS } from "@calcom/lib/constants"; import { APP_NAME, SUPPORT_MAIL_ADDRESS } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { EmptyScreen, Icon } from "@calcom/ui"; import { EmptyScreen } from "@calcom/ui";
import { FiAlertTriangle } from "@calcom/ui/components/icon";
type LicenseRequiredProps = { type LicenseRequiredProps = {
as?: keyof JSX.IntrinsicElements | ""; as?: keyof JSX.IntrinsicElements | "";
@@ -35,7 +36,7 @@ const LicenseRequired = ({ children, as = "", ...rest }: LicenseRequiredProps) =
children children
) : ( ) : (
<EmptyScreen <EmptyScreen
Icon={Icon.FiAlertTriangle} Icon={FiAlertTriangle}
headline={t("enterprise_license")} headline={t("enterprise_license")}
description={ description={
<div <div
@@ -4,7 +4,8 @@ import React, { AriaRole, ComponentType, Fragment } from "react";
import { APP_NAME, CONSOLE_URL, SUPPORT_MAIL_ADDRESS } from "@calcom/lib/constants"; import { APP_NAME, CONSOLE_URL, SUPPORT_MAIL_ADDRESS } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { EmptyScreen, Icon } from "@calcom/ui"; import { EmptyScreen } from "@calcom/ui";
import { FiAlertTriangle } from "@calcom/ui/components/icon";
type LicenseRequiredProps = { type LicenseRequiredProps = {
as?: keyof JSX.IntrinsicElements | ""; as?: keyof JSX.IntrinsicElements | "";
@@ -25,7 +26,7 @@ const LicenseRequired = ({ children, as = "", ...rest }: LicenseRequiredProps) =
children children
) : ( ) : (
<EmptyScreen <EmptyScreen
Icon={Icon.FiAlertTriangle} Icon={FiAlertTriangle}
headline={t("enterprise_license")} headline={t("enterprise_license")}
description={ description={
<div <div
@@ -14,7 +14,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import useTheme from "@calcom/lib/hooks/useTheme"; import useTheme from "@calcom/lib/hooks/useTheme";
import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/timeFormat"; import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/timeFormat";
import { localStorage } from "@calcom/lib/webstorage"; import { localStorage } from "@calcom/lib/webstorage";
import { Icon } from "@calcom/ui"; import { FiCreditCard } from "@calcom/ui/components/icon";
import type { PaymentPageProps } from "../pages/payment"; import type { PaymentPageProps } from "../pages/payment";
import PaymentComponent from "./Payment"; import PaymentComponent from "./Payment";
@@ -79,7 +79,7 @@ const PaymentPage: FC<PaymentPageProps> = (props) => {
aria-labelledby="modal-headline"> aria-labelledby="modal-headline">
<div> <div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
<Icon.FiCreditCard className="h-8 w-8 text-green-600" /> <FiCreditCard className="h-8 w-8 text-green-600" />
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
@@ -13,12 +13,12 @@ import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogTrigger, DialogTrigger,
Icon,
Label, Label,
Meta, Meta,
showToast, showToast,
AppSkeletonLoader as SkeletonLoader, AppSkeletonLoader as SkeletonLoader,
} from "@calcom/ui"; } from "@calcom/ui";
import { ClipboardCopyIcon, FiDatabase, FiTrash2 } from "@calcom/ui/components/icon";
export default function SAMLConfiguration({ teamId }: { teamId: number | null }) { export default function SAMLConfiguration({ teamId }: { teamId: number | null }) {
const { t } = useLocale(); const { t } = useLocale();
@@ -90,7 +90,7 @@ export default function SAMLConfiguration({ teamId }: { teamId: number | null })
<div> <div>
<Button <Button
color="secondary" color="secondary"
StartIcon={Icon.FiDatabase} StartIcon={FiDatabase}
onClick={() => { onClick={() => {
setConfigModal(true); setConfigModal(true);
}}> }}>
@@ -122,7 +122,7 @@ export default function SAMLConfiguration({ teamId }: { teamId: number | null })
}} }}
type="button" type="button"
className="px-4 text-base"> className="px-4 text-base">
<Icon.ClipboardCopyIcon className="h-5 w-5 text-gray-100" /> <ClipboardCopyIcon className="h-5 w-5 text-gray-100" />
{t("copy")} {t("copy")}
</Button> </Button>
</div> </div>
@@ -142,7 +142,7 @@ export default function SAMLConfiguration({ teamId }: { teamId: number | null })
}} }}
type="button" type="button"
className="px-4 text-base"> className="px-4 text-base">
<Icon.ClipboardCopyIcon className="h-5 w-5 text-gray-100" /> <ClipboardCopyIcon className="h-5 w-5 text-gray-100" />
{t("copy")} {t("copy")}
</Button> </Button>
</div> </div>
@@ -157,7 +157,7 @@ export default function SAMLConfiguration({ teamId }: { teamId: number | null })
<div className="mb-3 text-base font-semibold">{t("danger_zone")}</div> <div className="mb-3 text-base font-semibold">{t("danger_zone")}</div>
<Dialog> <Dialog>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button color="destructive" className="border" StartIcon={Icon.FiTrash2}> <Button color="destructive" className="border" StartIcon={FiTrash2}>
{t("delete_saml_configuration")} {t("delete_saml_configuration")}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
Loaded 100 of 181 files, more files were not shown because too many files have changed in this diff. Show more