Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Zoho Calendar #8144

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
68ab3bf
feat: add zoho calendar
murtajaziad Apr 8, 2023
3d7a699
remove log.debug
murtajaziad Apr 8, 2023
8a51e76
Merge branch 'main' into app/zohocalendar
murtajaziad Apr 8, 2023
c64440e
fix types
murtajaziad Apr 8, 2023
3d8c819
lint
murtajaziad Apr 8, 2023
9ee3b12
fix types and lint
murtajaziad Apr 8, 2023
6b861fd
lint
murtajaziad Apr 8, 2023
b046b4e
Apply suggestions from code review
hariombalhara Apr 19, 2023
e6c3772
Make changes to comply with new app structure - followed by app-store…
hariombalhara Apr 19, 2023
10bf10d
Add dead import
hariombalhara Apr 19, 2023
d56a491
Merge remote-tracking branch 'origin/main' into app/zohocalendar
hariombalhara Apr 19, 2023
a91e12f
More cleanup
hariombalhara Apr 19, 2023
2cfc402
Use slug as dirName if not explicilty set
hariombalhara Apr 19, 2023
62c38e9
Added instructions for obtaining Zoho Calendar Client ID and Secret
murtajaziad May 1, 2023
0e65ec8
Merge remote-tracking branch 'origin/main' into app/zohocalendar
hariombalhara May 10, 2023
86c235f
Reuse code
hariombalhara May 10, 2023
249b54c
Fix TS error
hariombalhara May 11, 2023
29e7384
Merge remote-tracking branch 'origin/main' into app/zohocalendar
hariombalhara May 11, 2023
37518ee
fix missing title and missing uemail
murtajaziad Jun 22, 2023
5935818
Merge branch 'main' into app/zohocalendar
alannnc Jun 27, 2023
735d9bf
Fixing app seed, event start end time on zoho app missmatch and fetch…
alannnc Jun 28, 2023
436020e
Merge branch 'main' into app/zohocalendar
alannnc Jun 28, 2023
0451429
Merge branch 'main' into app/zohocalendar
alannnc Jun 28, 2023
0788823
Merge branch 'main' into app/zohocalendar
alannnc Jun 29, 2023
6ce4754
Adjust CalendarService to match code style
alannnc Jun 29, 2023
1cb5334
Merge branch 'main' into app/zohocalendar
joeauyeung Jul 6, 2023
86e00c6
Merge branch 'main' into app/zohocalendar
joeauyeung Jul 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/app-store/apps.browser.generated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const InstallAppButtonMap = {
whereby: dynamic(() => import("./whereby/components/InstallAppButton")),
wipemycalother: dynamic(() => import("./wipemycalother/components/InstallAppButton")),
zapier: dynamic(() => import("./zapier/components/InstallAppButton")),
zohocalendar: dynamic(() => import("./zohocalendar/components/InstallAppButton")),
zoomvideo: dynamic(() => import("./zoomvideo/components/InstallAppButton")),
};
export const AppSettingsComponentsMap = {
Expand Down
2 changes: 2 additions & 0 deletions packages/app-store/apps.keys-schemas.generated.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-generated files shouldn't be committed.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { appKeysSchema as event_type_app_card_zod_ts } from "./templates/event-t
import { appKeysSchema as vital_zod_ts } from "./vital/zod";
import { appKeysSchema as wordpress_zod_ts } from "./wordpress/zod";
import { appKeysSchema as zapier_zod_ts } from "./zapier/zod";
import { appKeysSchema as zohocalendar_zod_ts } from "./zohocalendar/zod";
import { appKeysSchema as zoomvideo_zod_ts } from "./zoomvideo/zod";

export const appKeysSchemas = {
Expand All @@ -49,5 +50,6 @@ export const appKeysSchemas = {
vital: vital_zod_ts,
wordpress: wordpress_zod_ts,
zapier: zapier_zod_ts,
zohocalendar: zohocalendar_zod_ts,
zoomvideo: zoomvideo_zod_ts,
};
2 changes: 2 additions & 0 deletions packages/app-store/apps.metadata.generated.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-generated files shouldn't be committed.

Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import whereby_config_json from "./whereby/config.json";
import { metadata as wipemycalother__metadata_ts } from "./wipemycalother/_metadata";
import wordpress_config_json from "./wordpress/config.json";
import { metadata as zapier__metadata_ts } from "./zapier/_metadata";
import { metadata as zohocalendar__metadata_ts } from "./zohocalendar/_metadata";
import zohocrm_config_json from "./zohocrm/config.json";
import { metadata as zoomvideo__metadata_ts } from "./zoomvideo/_metadata";

Expand Down Expand Up @@ -120,6 +121,7 @@ export const appStoreMetadata = {
wipemycalother: wipemycalother__metadata_ts,
wordpress: wordpress_config_json,
zapier: zapier__metadata_ts,
zohocalendar: zohocalendar__metadata_ts,
zohocrm: zohocrm_config_json,
zoomvideo: zoomvideo__metadata_ts,
};
2 changes: 2 additions & 0 deletions packages/app-store/apps.schemas.generated.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-generated files shouldn't be committed.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { appDataSchema as event_type_app_card_zod_ts } from "./templates/event-t
import { appDataSchema as vital_zod_ts } from "./vital/zod";
import { appDataSchema as wordpress_zod_ts } from "./wordpress/zod";
import { appDataSchema as zapier_zod_ts } from "./zapier/zod";
import { appDataSchema as zohocalendar_zod_ts } from "./zohocalendar/zod";
import { appDataSchema as zoomvideo_zod_ts } from "./zoomvideo/zod";

export const appDataSchemas = {
Expand All @@ -49,5 +50,6 @@ export const appDataSchemas = {
vital: vital_zod_ts,
wordpress: wordpress_zod_ts,
zapier: zapier_zod_ts,
zohocalendar: zohocalendar_zod_ts,
zoomvideo: zoomvideo_zod_ts,
};
1 change: 1 addition & 0 deletions packages/app-store/apps.server.generated.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-generated files shouldn't be committed.

Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const apiHandlers = {
wipemycalother: import("./wipemycalother/api"),
wordpress: import("./wordpress/api"),
zapier: import("./zapier/api"),
zohocalendar: import("./zohocalendar/api"),
zohocrm: import("./zohocrm/api"),
zoomvideo: import("./zoomvideo/api"),
};
1 change: 1 addition & 0 deletions packages/app-store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const appStore = {
exchangecalendar: import("./exchangecalendar"),
facetime: import("./facetime"),
sylapsvideo: import("./sylapsvideo"),
zohocalendar: import("./zohocalendar"),
};

export default appStore;
6 changes: 6 additions & 0 deletions packages/app-store/zohocalendar/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
items:
- /api/app-store/zohocalendar/ZCal1.jpg
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
---

Zoho Calendar is an online business calendar that makes scheduling easy for you. You can use it to stay on top of your schedule and also share calendars with your team to keep everyone on the same page.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sydwardrae @Jaibles Please review App description

27 changes: 27 additions & 0 deletions packages/app-store/zohocalendar/_metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { AppMeta } from "@calcom/types/App";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing this file with config.json. It is deprecated and AppStore CLI doesn't create it.


import _package from "./package.json";

export const metadata = {
name: "Zoho Calendar",
description: _package.description,
installed: true,
type: "zoho_calendar",
title: "Zoho Calendar",
imageSrc: "/api/app-store/zohocalendar/icon.svg",
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
variant: "calendar",
category: "calendar",
categories: ["calendar"],
logo: "/api/app-store/zohocalendar/icon.svg",
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
publisher: "Cal.com",
rating: 5,
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
reviews: 69,
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
slug: "zoho-calendar",
trending: false,
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
url: "https://cal.com/",
verified: true,
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
email: "[email protected]",
dirName: "zohocalendar",
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
} as AppMeta;

export default metadata;
36 changes: 36 additions & 0 deletions packages/app-store/zohocalendar/api/add.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { stringify } from "querystring";
import { z } from "zod";

import { WEBAPP_URL } from "@calcom/lib/constants";

import { encodeOAuthState } from "../../_utils/encodeOAuthState";
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";

const zohoKeysSchema = z.object({
client_id: z.string(),
client_secret: z.string(),
});

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "GET") {
const appKeys = await getAppKeysFromSlug("zoho-calendar");
const { client_id } = zohoKeysSchema.parse(appKeys);

const state = encodeOAuthState(req);

const params = {
client_id,
response_type: "code",
redirect_uri: WEBAPP_URL + "/api/integrations/zohocalendar/callback",
scope: ["ZohoCalendar.calendar.ALL", "ZohoCalendar.event.ALL", "ZohoCalendar.freebusy.READ"],
access_type: "offline",
state,
prompt: "consent",
};

const query = stringify(params);

res.status(200).json({ url: `https://accounts.zoho.com/oauth/v2/auth?${query}` });
}
}
80 changes: 80 additions & 0 deletions packages/app-store/zohocalendar/api/callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { stringify } from "querystring";
import { z } from "zod";

import { WEBAPP_URL } from "@calcom/lib/constants";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import logger from "@calcom/lib/logger";
import prisma from "@calcom/prisma";

import { decodeOAuthState } from "../../_utils/decodeOAuthState";
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";
import getInstalledAppPath from "../../_utils/getInstalledAppPath";
import type { ZohoAuthCredentials } from "../types/ZohoCalendar";

const log = logger.getChildLogger({ prefix: [`[[zohocalendar/api/callback]`] });

const zohoKeysSchema = z.object({
hariombalhara marked this conversation as resolved.
Show resolved Hide resolved
client_id: z.string(),
client_secret: z.string(),
});

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { code } = req.query;
const state = decodeOAuthState(req);

if (code && typeof code !== "string") {
res.status(400).json({ message: "`code` must be a string" });
return;
}
if (!req.session?.user?.id) {
return res.status(401).json({ message: "You must be logged in to do this" });
}

const appKeys = await getAppKeysFromSlug("zoho-calendar");
const { client_id, client_secret } = zohoKeysSchema.parse(appKeys);

const params = {
client_id,
grant_type: "authorization_code",
client_secret,
redirect_uri: WEBAPP_URL + "/api/integrations/zohocalendar/callback",
code,
};

const query = stringify(params);

const response = await fetch(`https://accounts.zoho.com/oauth/v2/token?${query}`, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8",
},
});

const responseBody = await response.json();
console.log(responseBody);

if (!response.ok || responseBody.error) {
log.error("get access_token failed", responseBody);
return res.redirect("/apps/installed?error=" + JSON.stringify(responseBody));
}

const key: ZohoAuthCredentials = {
access_token: responseBody.access_token,
refresh_token: responseBody.refresh_token,
expires_in: Math.round(+new Date() / 1000 + responseBody.expires_in),
};

await prisma.credential.create({
data: {
type: "zoho_calendar",
key,
userId: req.session.user.id,
appId: "zoho-calendar",
},
});

res.redirect(
getSafeRedirectUrl(state?.returnTo) ?? getInstalledAppPath({ variant: "calendar", slug: "zoho-calendar" })
);
}
2 changes: 2 additions & 0 deletions packages/app-store/zohocalendar/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as add } from "./add";
export { default as callback } from "./callback";
18 changes: 18 additions & 0 deletions packages/app-store/zohocalendar/components/InstallAppButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { InstallAppButtonProps } from "@calcom/app-store/types";

import useAddAppMutation from "../../_utils/useAddAppMutation";

export default function InstallAppButton(props: InstallAppButtonProps) {
const mutation = useAddAppMutation("zoho_calendar");

return (
<>
{props.render({
onClick() {
mutation.mutate("");
},
loading: mutation.isLoading,
})}
</>
);
}
1 change: 1 addition & 0 deletions packages/app-store/zohocalendar/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as InstallAppButton } from "./InstallAppButton";
3 changes: 3 additions & 0 deletions packages/app-store/zohocalendar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * as api from "./api";
export * as lib from "./lib";
export { metadata } from "./_metadata";
Loading