feat: additional calendar selector for calendar settings atom (#16874)

* update translations

* fixup

* add onSuccess prop

* add additional calendar selector prop to add multiple calendars

* update props for calendar settings atom

* pass caledar redirect urls for google and apple calendar redirects

* fix merge conflicts

* add onSuccess prop to connect atoms

* fixup

* fixup

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
Rajiv Sahal
2024-10-10 09:02:40 +00:00
committed by GitHub
co-authored by Morgan
parent 513a58c91c
commit 34afc7b674
5 changed files with 104 additions and 7 deletions
@@ -2607,6 +2607,7 @@
"disable_email": "Disable email",
"grant_admin_api": "Grant Admin API Access",
"revoke_admin_api": "Revoke Admin API Access",
"add_calendar_label": "Add {{calendar}} Calendar",
"apple_connect_atom_label": "Connect Apple Calendar",
"apple_connect_atom_already_connected_label": "Connected Apple Calendar",
"apple_connect_atom_loading_label": "Checking Apple Calendar",
@@ -1,5 +1,6 @@
import { DestinationCalendarSettingsPlatformWrapper } from "../../destination-calendar/index";
import { SelectedCalendarsSettingsPlatformWrapper } from "../../selected-calendars/index";
import type { CalendarRedirectUrls } from "../../selected-calendars/wrappers/SelectedCalendarsSettingsPlatformWrapper";
type CalendarSettingsPlatformWrapperProps = {
classNames?: {
@@ -7,9 +8,13 @@ type CalendarSettingsPlatformWrapperProps = {
destinationCalendarSettingsCustomClassnames?: string;
selectedCalendarSettingsCustomClassnames?: string;
};
calendarRedirectUrls?: CalendarRedirectUrls;
};
export const CalendarSettingsPlatformWrapper = ({ classNames }: CalendarSettingsPlatformWrapperProps) => {
export const CalendarSettingsPlatformWrapper = ({
classNames,
calendarRedirectUrls,
}: CalendarSettingsPlatformWrapperProps) => {
return (
<div className={classNames?.calendarSettingsCustomClassnames}>
<DestinationCalendarSettingsPlatformWrapper
@@ -18,6 +23,7 @@ export const CalendarSettingsPlatformWrapper = ({ classNames }: CalendarSettings
/>
<SelectedCalendarsSettingsPlatformWrapper
classNames={classNames?.selectedCalendarSettingsCustomClassnames}
calendarRedirectUrls={calendarRedirectUrls}
/>
</div>
);
@@ -25,6 +25,7 @@ export type OAuthConnectProps = {
tooltip?: ReactNode;
tooltipSide?: "top" | "bottom" | "left" | "right";
isClickable?: boolean;
onSuccess?: () => void;
};
export const OAuthConnect: FC<
@@ -44,6 +45,7 @@ export const OAuthConnect: FC<
tooltip,
tooltipSide = "bottom",
isClickable,
onSuccess,
}) => {
const { connect } = useConnect(calendar, redir);
const { allowConnect, checked } = useCheck({
@@ -74,7 +76,10 @@ export const OAuthConnect: FC<
tooltipSide={tooltipSide}
tooltipOffset={10}
className={cn("", !isDisabled && "cursor-pointer", className)}
onClick={() => connect()}>
onClick={() => {
connect();
onSuccess?.();
}}>
{displayedLabel}
</Button>
</AtomsWrapper>
@@ -34,6 +34,7 @@ export const AppleConnect: FC<Partial<Omit<OAuthConnectProps, "redir">>> = ({
tooltip,
tooltipSide = "bottom",
isClickable,
onSuccess,
}) => {
const { t } = useLocale();
const form = useForm({
@@ -60,6 +61,7 @@ export const AppleConnect: FC<Partial<Omit<OAuthConnectProps, "redir">>> = ({
toast({
description: "Calendar credentials added successfully",
});
onSuccess?.();
}
},
onError: (err) => {
@@ -11,22 +11,37 @@ import {
List,
DisconnectIntegrationComponent,
Alert,
Button,
Dropdown,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@calcom/ui";
import { AppleConnect } from "../../connect/apple/AppleConnect";
import { useAddSelectedCalendar } from "../../hooks/calendars/useAddSelectedCalendar";
import { useDeleteCalendarCredentials } from "../../hooks/calendars/useDeleteCalendarCredentials";
import { useRemoveSelectedCalendar } from "../../hooks/calendars/useRemoveSelectedCalendar";
import { useConnectedCalendars } from "../../hooks/useConnectedCalendars";
import { Connect } from "../../index";
import { AtomsWrapper } from "../../src/components/atoms-wrapper";
import { Switch } from "../../src/components/ui/switch";
import { useToast } from "../../src/components/ui/use-toast";
import { SelectedCalendarsSettings } from "../SelectedCalendarsSettings";
export type CalendarRedirectUrls = {
google?: string;
outlook?: string;
};
type SelectedCalendarsSettingsPlatformWrapperProps = {
classNames?: string;
calendarRedirectUrls?: CalendarRedirectUrls;
};
export const SelectedCalendarsSettingsPlatformWrapper = ({
classNames = "mx-5 mb-6",
}: {
classNames?: string;
}) => {
calendarRedirectUrls,
}: SelectedCalendarsSettingsPlatformWrapperProps) => {
const { t } = useLocale();
const query = useConnectedCalendars({});
@@ -44,7 +59,7 @@ export const SelectedCalendarsSettingsPlatformWrapper = ({
return (
<SelectedCalendarsSettings classNames={classNames}>
<SelectedCalendarsSettingsHeading />
<SelectedCalendarsSettingsHeading calendarRedirectUrls={calendarRedirectUrls} />
<List noBorderTreatment className="p-6 pt-2">
{data.connectedCalendars.map((connectedCalendar) => {
if (!!connectedCalendar.calendars && connectedCalendar.calendars.length > 0) {
@@ -121,7 +136,11 @@ export const SelectedCalendarsSettingsPlatformWrapper = ({
);
};
const SelectedCalendarsSettingsHeading = () => {
const SelectedCalendarsSettingsHeading = ({
calendarRedirectUrls,
}: {
calendarRedirectUrls?: CalendarRedirectUrls;
}) => {
const { t } = useLocale();
return (
@@ -131,6 +150,11 @@ const SelectedCalendarsSettingsHeading = () => {
<h4 className="text-emphasis text-base font-semibold leading-5">{t("check_for_conflicts")}</h4>
<p className="text-default text-sm leading-tight">{t("select_calendars")}</p>
</div>
<div className="flex flex-col xl:flex-row xl:space-x-5">
<div className="flex items-center">
<PlatformAdditionalCalendarSelector calendarRedirectUrls={calendarRedirectUrls} />
</div>
</div>
</div>
</div>
);
@@ -244,3 +268,62 @@ const PlatformCalendarSwitch = (props: ICalendarSwitchProps) => {
</CalendarSwitchComponent>
);
};
const PlatformAdditionalCalendarSelector = ({
calendarRedirectUrls,
}: {
calendarRedirectUrls?: CalendarRedirectUrls;
}) => {
const { t } = useLocale();
const { refetch } = useConnectedCalendars({});
return (
<Dropdown modal={false}>
<DropdownMenuTrigger asChild>
<Button StartIcon="plus" color="secondary">
{t("add")}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<div>
<div>
<Connect.GoogleCalendar
isMultiCalendar={true}
isClickable={true}
tooltip={<></>}
redir={calendarRedirectUrls?.google ?? window.location.href}
label={t("add_calendar_label", { calendar: "Google" })}
loadingLabel={t("add_calendar_label", { calendar: "Google" })}
alreadyConnectedLabel={t("add_calendar_label", { calendar: "Google" })}
className="hover:bg-subtle hover:text-default cursor-pointer border-none bg-inherit text-inherit"
/>
</div>
<div>
<Connect.OutlookCalendar
isMultiCalendar={true}
isClickable={true}
tooltip={<></>}
redir={calendarRedirectUrls?.outlook ?? window.location.href}
label={t("add_calendar_label", { calendar: "Outlook" })}
loadingLabel={t("add_calendar_label", { calendar: "Outlook" })}
alreadyConnectedLabel={t("add_calendar_label", { calendar: "Outlook" })}
className="hover:bg-subtle hover:text-default cursor-pointer border-none bg-inherit text-inherit"
/>
</div>
<div>
<AppleConnect
onSuccess={refetch}
isClickable={true}
isMultiCalendar={true}
tooltip={<></>}
label={t("add_calendar_label", { calendar: "Apple" })}
loadingLabel={t("add_calendar_label", { calendar: "Apple" })}
alreadyConnectedLabel={t("add_calendar_label", { calendar: "Apple" })}
className="hover:bg-subtle hover:text-default cursor-pointer border-none bg-inherit text-inherit"
/>
</div>
</div>
</DropdownMenuContent>
</Dropdown>
);
};