fix: /getting-started/connected-calendar Toggle the first calendar on (#9028)

* [CAL-115] /getting-started/connected-calendar Toggle the first calendar on

* Fix lint error

* Fix error shown after completion of onboarding by connecting to calendars and playing around with toggle

* Fix type errors

* Fix first calendar selected even in all the screens wherever connectedCalendars is used
This commit is contained in:
Anwar Sadath 2023-06-05 14:51:50 +05:30 committed by GitHub
parent 64796a96fc
commit 7f7d80e653
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 5 deletions

View File

@ -15,7 +15,7 @@ interface IConnectCalendarsProps {
const ConnectedCalendars = (props: IConnectCalendarsProps) => {
const { nextStep } = props;
const queryConnectedCalendars = trpc.viewer.connectedCalendars.useQuery();
const queryConnectedCalendars = trpc.viewer.connectedCalendars.useQuery({ onboarding: true });
const { t } = useLocale();
const queryIntegrations = trpc.viewer.integrations.useQuery({ variant: "calendar", onlyInstalled: false });

View File

@ -4,6 +4,7 @@ import { ZAppByIdInputSchema } from "./appById.schema";
import { ZAppCredentialsByTypeInputSchema } from "./appCredentialsByType.schema";
import { ZAppsInputSchema } from "./apps.schema";
import { ZAwayInputSchema } from "./away.schema";
import { ZConnectedCalendarsInputSchema } from "./connectedCalendars.schema";
import { ZDeleteCredentialInputSchema } from "./deleteCredential.schema";
import { ZDeleteMeInputSchema } from "./deleteMe.schema";
import { ZEventTypeOrderInputSchema } from "./eventTypeOrder.schema";
@ -110,7 +111,7 @@ export const loggedInViewerRouter = router({
return UNSTABLE_HANDLER_CACHE.away({ ctx, input });
}),
connectedCalendars: authedProcedure.query(async ({ ctx }) => {
connectedCalendars: authedProcedure.input(ZConnectedCalendarsInputSchema).query(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.connectedCalendars) {
UNSTABLE_HANDLER_CACHE.connectedCalendars = (
await import("./connectedCalendars.handler")
@ -122,7 +123,7 @@ export const loggedInViewerRouter = router({
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.connectedCalendars({ ctx });
return UNSTABLE_HANDLER_CACHE.connectedCalendars({ ctx, input });
}),
setDestinationCalendar: authedProcedure

View File

@ -5,14 +5,18 @@ import { prisma } from "@calcom/prisma";
import { AppCategories } from "@calcom/prisma/enums";
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
import type { TConnectedCalendarsInputSchema } from "./connectedCalendars.schema";
type ConnectedCalendarsOptions = {
ctx: {
user: NonNullable<TrpcSessionUser>;
};
input: TConnectedCalendarsInputSchema;
};
export const connectedCalendarsHandler = async ({ ctx }: ConnectedCalendarsOptions) => {
export const connectedCalendarsHandler = async ({ ctx, input }: ConnectedCalendarsOptions) => {
const { user } = ctx;
const onboarding = input?.onboarding || false;
const userCredentials = await prisma.credential.findMany({
where: {
@ -33,6 +37,12 @@ export const connectedCalendarsHandler = async ({ ctx }: ConnectedCalendarsOptio
user.selectedCalendars,
user.destinationCalendar?.externalId
);
let toggledCalendarDetails:
| {
externalId: string;
integration: string;
}
| undefined;
if (connectedCalendars.length === 0) {
/* As there are no connected calendars, delete the destination calendar if it exists */
@ -48,6 +58,19 @@ export const connectedCalendarsHandler = async ({ ctx }: ConnectedCalendarsOptio
So create a default destination calendar with the first primary connected calendar
*/
const { integration = "", externalId = "", credentialId } = connectedCalendars[0].primary ?? {};
// Select the first calendar matching the primary by default since that will also be the destination calendar
if (onboarding && externalId) {
const calendarIndex = (connectedCalendars[0].calendars || []).findIndex(
(item) => item.externalId === externalId && item.integration === integration
);
if (calendarIndex >= 0 && connectedCalendars[0].calendars) {
connectedCalendars[0].calendars[calendarIndex].isSelected = true;
toggledCalendarDetails = {
externalId,
integration,
};
}
}
user.destinationCalendar = await prisma.destinationCalendar.create({
data: {
userId: user.id,
@ -70,6 +93,19 @@ export const connectedCalendarsHandler = async ({ ctx }: ConnectedCalendarsOptio
if (!destinationCal) {
// If destinationCalendar is out of date, update it with the first primary connected calendar
const { integration = "", externalId = "" } = connectedCalendars[0].primary ?? {};
// Select the first calendar matching the primary by default since that will also be the destination calendar
if (onboarding && externalId) {
const calendarIndex = (connectedCalendars[0].calendars || []).findIndex(
(item) => item.externalId === externalId && item.integration === integration
);
if (calendarIndex >= 0 && connectedCalendars[0].calendars) {
connectedCalendars[0].calendars[calendarIndex].isSelected = true;
toggledCalendarDetails = {
externalId,
integration,
};
}
}
user.destinationCalendar = await prisma.destinationCalendar.update({
where: { userId: user.id },
data: {
@ -77,9 +113,49 @@ export const connectedCalendarsHandler = async ({ ctx }: ConnectedCalendarsOptio
externalId,
},
});
} else if (onboarding && !destinationCal.isSelected) {
// Mark the destination calendar as selected in the calendar list
// We use every so that we can exit early once we find the matching calendar
connectedCalendars.every((cal) => {
const index = (cal.calendars || []).findIndex(
(calendar) =>
calendar.externalId === destinationCal.externalId &&
calendar.integration === destinationCal.integration
);
if (index >= 0 && cal.calendars) {
cal.calendars[index].isSelected = true;
toggledCalendarDetails = {
externalId: destinationCal.externalId,
integration: destinationCal.integration || "",
};
return false;
}
return true;
});
}
}
// Insert the newly toggled record to the DB
if (toggledCalendarDetails) {
await prisma.selectedCalendar.upsert({
where: {
userId_integration_externalId: {
userId: user.id,
integration: toggledCalendarDetails.integration,
externalId: toggledCalendarDetails.externalId,
},
},
create: {
userId: user.id,
integration: toggledCalendarDetails.integration,
externalId: toggledCalendarDetails.externalId,
},
// already exists
update: {},
});
}
return {
connectedCalendars,
destinationCalendar: {

View File

@ -1 +1,9 @@
export {};
import { z } from "zod";
export const ZConnectedCalendarsInputSchema = z
.object({
onboarding: z.boolean().optional(),
})
.optional();
export type TConnectedCalendarsInputSchema = z.infer<typeof ZConnectedCalendarsInputSchema>;