Chore/salesforce prep work (#5648)
* WIP
* warnings and errors, and working app
* Refresh token now usable
* Correcting env.appStore.example
* Reverting changes that will come from Sendgrid App PR
* Resetting with main
* Renaming all othercalendars
* Fixing types
* Renaming leftovers
* More renaming stuff
* Format readme
* Adds prettier override for website wordlist
* Omit salesforce app in this PR
* Cleanup
* Update AppSettings.tsx
* Revert "Cleanup"
This reverts commit 41f94c52c3
.
* Update yarn.lock
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
|
@ -11,6 +11,9 @@
|
||||||
# - ZOOM
|
# - ZOOM
|
||||||
# - GIPHY
|
# - GIPHY
|
||||||
# - VITAL
|
# - VITAL
|
||||||
|
# - ZAPIER
|
||||||
|
# - LARK
|
||||||
|
# - WEB3
|
||||||
|
|
||||||
# - APP STORE **********************************************************************************************
|
# - APP STORE **********************************************************************************************
|
||||||
# ⚠️ ⚠️ ⚠️ THESE WILL BE MIGRATED TO THE DATABASE TO PREVENT AWS's 4KB ENV QUOTA ⚠️ ⚠️ ⚠️
|
# ⚠️ ⚠️ ⚠️ THESE WILL BE MIGRATED TO THE DATABASE TO PREVENT AWS's 4KB ENV QUOTA ⚠️ ⚠️ ⚠️
|
||||||
|
@ -88,7 +91,7 @@ VITAL_REGION="us"
|
||||||
# @see https://github.com/calcom/cal.com/blob/main/packages/app-store/zapier/README.md
|
# @see https://github.com/calcom/cal.com/blob/main/packages/app-store/zapier/README.md
|
||||||
ZAPIER_INVITE_LINK=""
|
ZAPIER_INVITE_LINK=""
|
||||||
|
|
||||||
# - LARK
|
# - LARK
|
||||||
# Needed to enable Lark Calendar integration and Login with Lark
|
# Needed to enable Lark Calendar integration and Login with Lark
|
||||||
# @see <https://open.larksuite.com/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/g>
|
# @see <https://open.larksuite.com/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/g>
|
||||||
LARK_OPEN_APP_ID=""
|
LARK_OPEN_APP_ID=""
|
||||||
|
|
|
@ -387,7 +387,7 @@ following
|
||||||
4. Fill in any information you want in the "App info" tab
|
4. Fill in any information you want in the "App info" tab
|
||||||
5. Go to tab "Auth"
|
5. Go to tab "Auth"
|
||||||
6. Now copy the Client ID and Client Secret to your .env file into the `HUBSPOT_CLIENT_ID` and `HUBSPOT_CLIENT_SECRET` fields.
|
6. Now copy the Client ID and Client Secret to your .env file into the `HUBSPOT_CLIENT_ID` and `HUBSPOT_CLIENT_SECRET` fields.
|
||||||
7. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/hubspotothercalendar/callback` replacing Cal.com URL with the URI at which your application runs.
|
7. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/hubspot/callback` replacing Cal.com URL with the URI at which your application runs.
|
||||||
8. In the "Scopes" section at the bottom of the page, make sure you select "Read" and "Write" for scope called `crm.objects.contacts`
|
8. In the "Scopes" section at the bottom of the page, make sure you select "Read" and "Write" for scope called `crm.objects.contacts`
|
||||||
9. Click the "Save" button at the bottom footer.
|
9. Click the "Save" button at the bottom footer.
|
||||||
10. You're good to go. Now you can see any booking in Cal.com created as a meeting in HubSpot for your contacts.
|
10. You're good to go. Now you can see any booking in Cal.com created as a meeting in HubSpot for your contacts.
|
||||||
|
|
|
@ -41,14 +41,14 @@ const config: Config = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: "@calcom/closecom",
|
displayName: "@calcom/closecom",
|
||||||
roots: ["<rootDir>/packages/app-store/closecomothercalendar"],
|
roots: ["<rootDir>/packages/app-store/closecom"],
|
||||||
testMatch: ["**/test/lib/**/*.(spec|test).(ts|tsx|js)"],
|
testMatch: ["**/test/lib/**/*.(spec|test).(ts|tsx|js)"],
|
||||||
transform: {
|
transform: {
|
||||||
"^.+\\.ts?$": "ts-jest",
|
"^.+\\.ts?$": "ts-jest",
|
||||||
},
|
},
|
||||||
transformIgnorePatterns: ["/node_modules/", "^.+\\.module\\.(css|sass|scss)$"],
|
transformIgnorePatterns: ["/node_modules/", "^.+\\.module\\.(css|sass|scss)$"],
|
||||||
testEnvironment: "jsdom",
|
testEnvironment: "jsdom",
|
||||||
setupFiles: ["<rootDir>/packages/app-store/closecomothercalendar/test/globals.ts"],
|
setupFiles: ["<rootDir>/packages/app-store/closecom/test/globals.ts"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: "@calcom/routing-forms",
|
displayName: "@calcom/routing-forms",
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const AppSetupMap = {
|
||||||
"exchange2016-calendar": dynamic(() => import("../../exchange2016calendar/pages/setup")),
|
"exchange2016-calendar": dynamic(() => import("../../exchange2016calendar/pages/setup")),
|
||||||
"caldav-calendar": dynamic(() => import("../../caldavcalendar/pages/setup")),
|
"caldav-calendar": dynamic(() => import("../../caldavcalendar/pages/setup")),
|
||||||
zapier: dynamic(() => import("../../zapier/pages/setup")),
|
zapier: dynamic(() => import("../../zapier/pages/setup")),
|
||||||
closecom: dynamic(() => import("../../closecomothercalendar/pages/setup")),
|
closecom: dynamic(() => import("../../closecom/pages/setup")),
|
||||||
sendgrid: dynamic(() => import("../../sendgrid/pages/setup")),
|
sendgrid: dynamic(() => import("../../sendgrid/pages/setup")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ const log = logger.getChildLogger({ prefix: ["CalendarManager"] });
|
||||||
export const getCalendar = (credential: CredentialPayload | null): Calendar | null => {
|
export const getCalendar = (credential: CredentialPayload | null): Calendar | null => {
|
||||||
if (!credential || !credential.key) return null;
|
if (!credential || !credential.key) return null;
|
||||||
let { type: calendarType } = credential;
|
let { type: calendarType } = credential;
|
||||||
if (calendarType === "sendgrid_other_calendar") {
|
if (calendarType?.endsWith("_other_calendar")) {
|
||||||
calendarType = "sendgrid";
|
calendarType = calendarType.split("_other_calendar")[0];
|
||||||
}
|
}
|
||||||
const calendarApp = appStore[calendarType.split("_").join("") as keyof typeof appStore];
|
const calendarApp = appStore[calendarType.split("_").join("") as keyof typeof appStore];
|
||||||
if (!(calendarApp && "lib" in calendarApp && "CalendarService" in calendarApp.lib)) {
|
if (!(calendarApp && "lib" in calendarApp && "CalendarService" in calendarApp.lib)) {
|
||||||
|
|
|
@ -36,8 +36,8 @@ function useAddAppMutation(_type: App["type"] | null, options?: UseAddAppMutatio
|
||||||
isOmniInstall = variables.isOmniInstall;
|
isOmniInstall = variables.isOmniInstall;
|
||||||
type = variables.type;
|
type = variables.type;
|
||||||
}
|
}
|
||||||
if (type === "sendgrid_other_calendar") {
|
if (type?.endsWith("_other_calendar")) {
|
||||||
type = "sendgrid";
|
type = type.split("_other_calendar")[0];
|
||||||
}
|
}
|
||||||
const state: IntegrationOAuthCallbackState = {
|
const state: IntegrationOAuthCallbackState = {
|
||||||
returnTo:
|
returnTo:
|
||||||
|
@ -73,7 +73,7 @@ function useAddAppMutation(_type: App["type"] | null, options?: UseAddAppMutatio
|
||||||
gotoUrl(json.url, json.newTab);
|
gotoUrl(json.url, json.newTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { setupPending: !externalUrl && json.url.endsWith("/setup") };
|
return { setupPending: externalUrl || json.url.endsWith("/setup") };
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
return mutation;
|
return mutation;
|
||||||
|
|
|
@ -8,12 +8,12 @@ export const InstallAppButtonMap = {
|
||||||
applecalendar: dynamic(() => import("./applecalendar/components/InstallAppButton")),
|
applecalendar: dynamic(() => import("./applecalendar/components/InstallAppButton")),
|
||||||
around: dynamic(() => import("./around/components/InstallAppButton")),
|
around: dynamic(() => import("./around/components/InstallAppButton")),
|
||||||
caldavcalendar: dynamic(() => import("./caldavcalendar/components/InstallAppButton")),
|
caldavcalendar: dynamic(() => import("./caldavcalendar/components/InstallAppButton")),
|
||||||
closecomothercalendar: dynamic(() => import("./closecomothercalendar/components/InstallAppButton")),
|
closecom: dynamic(() => import("./closecom/components/InstallAppButton")),
|
||||||
exchange2013calendar: dynamic(() => import("./exchange2013calendar/components/InstallAppButton")),
|
exchange2013calendar: dynamic(() => import("./exchange2013calendar/components/InstallAppButton")),
|
||||||
exchange2016calendar: dynamic(() => import("./exchange2016calendar/components/InstallAppButton")),
|
exchange2016calendar: dynamic(() => import("./exchange2016calendar/components/InstallAppButton")),
|
||||||
exchangecalendar: dynamic(() => import("./exchangecalendar/components/InstallAppButton")),
|
exchangecalendar: dynamic(() => import("./exchangecalendar/components/InstallAppButton")),
|
||||||
googlecalendar: dynamic(() => import("./googlecalendar/components/InstallAppButton")),
|
googlecalendar: dynamic(() => import("./googlecalendar/components/InstallAppButton")),
|
||||||
hubspotothercalendar: dynamic(() => import("./hubspotothercalendar/components/InstallAppButton")),
|
hubspot: dynamic(() => import("./hubspot/components/InstallAppButton")),
|
||||||
huddle01video: dynamic(() => import("./huddle01video/components/InstallAppButton")),
|
huddle01video: dynamic(() => import("./huddle01video/components/InstallAppButton")),
|
||||||
jitsivideo: dynamic(() => import("./jitsivideo/components/InstallAppButton")),
|
jitsivideo: dynamic(() => import("./jitsivideo/components/InstallAppButton")),
|
||||||
larkcalendar: dynamic(() => import("./larkcalendar/components/InstallAppButton")),
|
larkcalendar: dynamic(() => import("./larkcalendar/components/InstallAppButton")),
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { metadata as applecalendar_meta } from "./applecalendar/_metadata";
|
||||||
import { metadata as around_meta } from "./around/_metadata";
|
import { metadata as around_meta } from "./around/_metadata";
|
||||||
import { metadata as caldavcalendar_meta } from "./caldavcalendar/_metadata";
|
import { metadata as caldavcalendar_meta } from "./caldavcalendar/_metadata";
|
||||||
import { metadata as campfire_meta } from "./campfire/_metadata";
|
import { metadata as campfire_meta } from "./campfire/_metadata";
|
||||||
import { metadata as closecomothercalendar_meta } from "./closecomothercalendar/_metadata";
|
import { metadata as closecom_meta } from "./closecom/_metadata";
|
||||||
import { metadata as dailyvideo_meta } from "./dailyvideo/_metadata";
|
import { metadata as dailyvideo_meta } from "./dailyvideo/_metadata";
|
||||||
import { metadata as routing_forms_meta } from "./ee/routing-forms/_metadata";
|
import { metadata as routing_forms_meta } from "./ee/routing-forms/_metadata";
|
||||||
import { metadata as exchange2013calendar_meta } from "./exchange2013calendar/_metadata";
|
import { metadata as exchange2013calendar_meta } from "./exchange2013calendar/_metadata";
|
||||||
|
@ -17,7 +17,7 @@ import { metadata as ga4_meta } from "./ga4/_metadata";
|
||||||
import { metadata as giphy_meta } from "./giphy/_metadata";
|
import { metadata as giphy_meta } from "./giphy/_metadata";
|
||||||
import { metadata as googlecalendar_meta } from "./googlecalendar/_metadata";
|
import { metadata as googlecalendar_meta } from "./googlecalendar/_metadata";
|
||||||
import { metadata as googlevideo_meta } from "./googlevideo/_metadata";
|
import { metadata as googlevideo_meta } from "./googlevideo/_metadata";
|
||||||
import { metadata as hubspotothercalendar_meta } from "./hubspotothercalendar/_metadata";
|
import { metadata as hubspot_meta } from "./hubspot/_metadata";
|
||||||
import { metadata as huddle01video_meta } from "./huddle01video/_metadata";
|
import { metadata as huddle01video_meta } from "./huddle01video/_metadata";
|
||||||
import { metadata as jitsivideo_meta } from "./jitsivideo/_metadata";
|
import { metadata as jitsivideo_meta } from "./jitsivideo/_metadata";
|
||||||
import { metadata as larkcalendar_meta } from "./larkcalendar/_metadata";
|
import { metadata as larkcalendar_meta } from "./larkcalendar/_metadata";
|
||||||
|
@ -49,7 +49,7 @@ export const appStoreMetadata = {
|
||||||
around: around_meta,
|
around: around_meta,
|
||||||
caldavcalendar: caldavcalendar_meta,
|
caldavcalendar: caldavcalendar_meta,
|
||||||
campfire: campfire_meta,
|
campfire: campfire_meta,
|
||||||
closecomothercalendar: closecomothercalendar_meta,
|
closecom: closecom_meta,
|
||||||
dailyvideo: dailyvideo_meta,
|
dailyvideo: dailyvideo_meta,
|
||||||
"routing-forms": routing_forms_meta,
|
"routing-forms": routing_forms_meta,
|
||||||
exchange2013calendar: exchange2013calendar_meta,
|
exchange2013calendar: exchange2013calendar_meta,
|
||||||
|
@ -60,7 +60,7 @@ export const appStoreMetadata = {
|
||||||
giphy: giphy_meta,
|
giphy: giphy_meta,
|
||||||
googlecalendar: googlecalendar_meta,
|
googlecalendar: googlecalendar_meta,
|
||||||
googlevideo: googlevideo_meta,
|
googlevideo: googlevideo_meta,
|
||||||
hubspotothercalendar: hubspotothercalendar_meta,
|
hubspot: hubspot_meta,
|
||||||
huddle01video: huddle01video_meta,
|
huddle01video: huddle01video_meta,
|
||||||
jitsivideo: jitsivideo_meta,
|
jitsivideo: jitsivideo_meta,
|
||||||
larkcalendar: larkcalendar_meta,
|
larkcalendar: larkcalendar_meta,
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const apiHandlers = {
|
||||||
around: import("./around/api"),
|
around: import("./around/api"),
|
||||||
caldavcalendar: import("./caldavcalendar/api"),
|
caldavcalendar: import("./caldavcalendar/api"),
|
||||||
campfire: import("./campfire/api"),
|
campfire: import("./campfire/api"),
|
||||||
closecomothercalendar: import("./closecomothercalendar/api"),
|
closecom: import("./closecom/api"),
|
||||||
"routing-forms": import("./ee/routing-forms/api"),
|
"routing-forms": import("./ee/routing-forms/api"),
|
||||||
exchange2013calendar: import("./exchange2013calendar/api"),
|
exchange2013calendar: import("./exchange2013calendar/api"),
|
||||||
exchange2016calendar: import("./exchange2016calendar/api"),
|
exchange2016calendar: import("./exchange2016calendar/api"),
|
||||||
|
@ -16,7 +16,7 @@ export const apiHandlers = {
|
||||||
ga4: import("./ga4/api"),
|
ga4: import("./ga4/api"),
|
||||||
giphy: import("./giphy/api"),
|
giphy: import("./giphy/api"),
|
||||||
googlecalendar: import("./googlecalendar/api"),
|
googlecalendar: import("./googlecalendar/api"),
|
||||||
hubspotothercalendar: import("./hubspotothercalendar/api"),
|
hubspot: import("./hubspot/api"),
|
||||||
huddle01video: import("./huddle01video/api"),
|
huddle01video: import("./huddle01video/api"),
|
||||||
jitsivideo: import("./jitsivideo/api"),
|
jitsivideo: import("./jitsivideo/api"),
|
||||||
larkcalendar: import("./larkcalendar/api"),
|
larkcalendar: import("./larkcalendar/api"),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
items:
|
items:
|
||||||
- /api/app-store/closecomothercalendar/1.jpg
|
- /api/app-store/closecom/1.jpg
|
||||||
- /api/app-store/closecomothercalendar/2.jpg
|
- /api/app-store/closecom/2.jpg
|
||||||
- /api/app-store/closecomothercalendar/3.jpg
|
- /api/app-store/closecom/3.jpg
|
||||||
- /api/app-store/closecomothercalendar/4.jpg
|
- /api/app-store/closecom/4.jpg
|
||||||
- /api/app-store/closecomothercalendar/5.jpg
|
- /api/app-store/closecom/5.jpg
|
||||||
---
|
---
|
||||||
|
|
||||||
- Close is a modern CRM with build-in sales communication tools for email, phone, SMS, and meetings.
|
- Close is a modern CRM with build-in sales communication tools for email, phone, SMS, and meetings.
|
|
@ -4,8 +4,8 @@
|
||||||
"title": "Close.com",
|
"title": "Close.com",
|
||||||
"slug": "closecom",
|
"slug": "closecom",
|
||||||
"type": "closecom_other_calendar",
|
"type": "closecom_other_calendar",
|
||||||
"imageSrc": "/api/app-store/closecomothercalendar/icon.svg",
|
"imageSrc": "/api/app-store/closecom/icon.svg",
|
||||||
"logo": "/api/app-store/closecomothercalendar/icon.svg",
|
"logo": "/api/app-store/closecom/icon.svg",
|
||||||
"url": "https://cal.com/apps/closecom",
|
"url": "https://cal.com/apps/closecom",
|
||||||
"variant": "other",
|
"variant": "other",
|
||||||
"categories": ["other"],
|
"categories": ["other"],
|
|
@ -42,7 +42,7 @@ export default function CloseComSetup() {
|
||||||
<div>
|
<div>
|
||||||
{/* eslint-disable @next/next/no-img-element */}
|
{/* eslint-disable @next/next/no-img-element */}
|
||||||
<img
|
<img
|
||||||
src="/api/app-store/closecomothercalendar/icon.svg"
|
src="/api/app-store/closecom/icon.svg"
|
||||||
alt="Apple Calendar"
|
alt="Apple Calendar"
|
||||||
className="h-12 w-12 max-w-2xl"
|
className="h-12 w-12 max-w-2xl"
|
||||||
/>
|
/>
|
||||||
|
@ -65,7 +65,7 @@ export default function CloseComSetup() {
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
handleSubmit={async (values) => {
|
handleSubmit={async (values) => {
|
||||||
const res = await fetch("/api/integrations/closecomothercalendar/add", {
|
const res = await fetch("/api/integrations/closecom/add", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(values),
|
body: JSON.stringify(values),
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -122,7 +122,7 @@ export default function CloseComSetup() {
|
||||||
if (!check) return;
|
if (!check) return;
|
||||||
const api_key = form.getValues("api_key");
|
const api_key = form.getValues("api_key");
|
||||||
setTestLoading(true);
|
setTestLoading(true);
|
||||||
const res = await fetch("/api/integrations/closecomothercalendar/check", {
|
const res = await fetch("/api/integrations/closecom/check", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({ api_key }),
|
body: JSON.stringify({ api_key }),
|
||||||
headers: {
|
headers: {
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
items:
|
items:
|
||||||
- /api/app-store/hubspotothercalendar/hubspot01.webp
|
- /api/app-store/hubspot/hubspot01.webp
|
||||||
---
|
---
|
||||||
|
|
||||||
HubSpot is a cloud-based CRM designed to help align sales and marketing teams, foster sales enablement, boost ROI and optimize your inbound marketing strategy to generate more, qualified leads.
|
HubSpot is a cloud-based CRM designed to help align sales and marketing teams, foster sales enablement, boost ROI and optimize your inbound marketing strategy to generate more, qualified leads.
|
|
@ -7,9 +7,9 @@ export const metadata = {
|
||||||
installed: !!process.env.HUBSPOT_CLIENT_ID,
|
installed: !!process.env.HUBSPOT_CLIENT_ID,
|
||||||
description: _package.description,
|
description: _package.description,
|
||||||
type: "hubspot_other_calendar",
|
type: "hubspot_other_calendar",
|
||||||
imageSrc: "/api/app-store/hubspotothercalendar/icon.svg",
|
imageSrc: "/api/app-store/hubspot/icon.svg",
|
||||||
variant: "other_calendar",
|
variant: "other_calendar",
|
||||||
logo: "/api/app-store/hubspotothercalendar/icon.svg",
|
logo: "/api/app-store/hubspot/icon.svg",
|
||||||
publisher: "Cal.com",
|
publisher: "Cal.com",
|
||||||
url: "https://hubspot.com/",
|
url: "https://hubspot.com/",
|
||||||
verified: true,
|
verified: true,
|
|
@ -17,7 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
if (typeof appKeys.client_id === "string") client_id = appKeys.client_id;
|
if (typeof appKeys.client_id === "string") client_id = appKeys.client_id;
|
||||||
if (!client_id) return res.status(400).json({ message: "HubSpot client id missing." });
|
if (!client_id) return res.status(400).json({ message: "HubSpot client id missing." });
|
||||||
|
|
||||||
const redirectUri = WEBAPP_URL + "/api/integrations/hubspotothercalendar/callback";
|
const redirectUri = WEBAPP_URL + "/api/integrations/hubspot/callback";
|
||||||
const url = hubspotClient.oauth.getAuthorizationUrl(client_id, redirectUri, scopes.join(" "));
|
const url = hubspotClient.oauth.getAuthorizationUrl(client_id, redirectUri, scopes.join(" "));
|
||||||
res.status(200).json({ url });
|
res.status(200).json({ url });
|
||||||
}
|
}
|
|
@ -39,7 +39,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||||
const hubspotToken: HubspotToken = await hubspotClient.oauth.tokensApi.createToken(
|
const hubspotToken: HubspotToken = await hubspotClient.oauth.tokensApi.createToken(
|
||||||
"authorization_code",
|
"authorization_code",
|
||||||
code,
|
code,
|
||||||
WEBAPP_URL + "/api/integrations/hubspotothercalendar/callback",
|
WEBAPP_URL + "/api/integrations/hubspot/callback",
|
||||||
client_id,
|
client_id,
|
||||||
client_secret
|
client_secret
|
||||||
);
|
);
|
|
@ -23,7 +23,7 @@ import type { HubspotToken } from "../api/callback";
|
||||||
|
|
||||||
const hubspotClient = new hubspot.Client();
|
const hubspotClient = new hubspot.Client();
|
||||||
|
|
||||||
export default class HubspotOtherCalendarService implements Calendar {
|
export default class HubspotCalendarService implements Calendar {
|
||||||
private url = "";
|
private url = "";
|
||||||
private integrationName = "";
|
private integrationName = "";
|
||||||
private auth: Promise<{ getToken: () => Promise<any> }>;
|
private auth: Promise<{ getToken: () => Promise<any> }>;
|
||||||
|
@ -168,7 +168,7 @@ export default class HubspotOtherCalendarService implements Calendar {
|
||||||
const hubspotRefreshToken: HubspotToken = await hubspotClient.oauth.tokensApi.createToken(
|
const hubspotRefreshToken: HubspotToken = await hubspotClient.oauth.tokensApi.createToken(
|
||||||
"refresh_token",
|
"refresh_token",
|
||||||
undefined,
|
undefined,
|
||||||
WEBAPP_URL + "/api/integrations/hubspotothercalendar/callback",
|
WEBAPP_URL + "/api/integrations/hubspot/callback",
|
||||||
this.client_id,
|
this.client_id,
|
||||||
this.client_secret,
|
this.client_secret,
|
||||||
refreshToken
|
refreshToken
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "@calcom/hubspotothercalendar",
|
"name": "@calcom/hubspot",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"main": "./index.ts",
|
"main": "./index.ts",
|
||||||
"description": "HubSpot is a cloud-based CRM designed to help align sales and marketing teams, foster sales enablement, boost ROI and optimize your inbound marketing strategy to generate more, qualified leads.",
|
"description": "HubSpot is a cloud-based CRM designed to help align sales and marketing teams, foster sales enablement, boost ROI and optimize your inbound marketing strategy to generate more, qualified leads.",
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -1,7 +1,7 @@
|
||||||
// import * as example from "./_example";
|
// import * as example from "./_example";
|
||||||
import * as applecalendar from "./applecalendar";
|
import * as applecalendar from "./applecalendar";
|
||||||
import * as caldavcalendar from "./caldavcalendar";
|
import * as caldavcalendar from "./caldavcalendar";
|
||||||
import * as closecomothercalendar from "./closecomothercalendar";
|
import * as closecom from "./closecom";
|
||||||
import * as dailyvideo from "./dailyvideo";
|
import * as dailyvideo from "./dailyvideo";
|
||||||
import * as exchange2013calendar from "./exchange2013calendar";
|
import * as exchange2013calendar from "./exchange2013calendar";
|
||||||
import * as exchange2016calendar from "./exchange2016calendar";
|
import * as exchange2016calendar from "./exchange2016calendar";
|
||||||
|
@ -9,7 +9,7 @@ import * as exchangecalendar from "./exchangecalendar";
|
||||||
import * as giphy from "./giphy";
|
import * as giphy from "./giphy";
|
||||||
import * as googlecalendar from "./googlecalendar";
|
import * as googlecalendar from "./googlecalendar";
|
||||||
import * as googlevideo from "./googlevideo";
|
import * as googlevideo from "./googlevideo";
|
||||||
import * as hubspotothercalendar from "./hubspotothercalendar";
|
import * as hubspot from "./hubspot";
|
||||||
import * as huddle01video from "./huddle01video";
|
import * as huddle01video from "./huddle01video";
|
||||||
import * as jitsivideo from "./jitsivideo";
|
import * as jitsivideo from "./jitsivideo";
|
||||||
import * as larkcalendar from "./larkcalendar";
|
import * as larkcalendar from "./larkcalendar";
|
||||||
|
@ -27,11 +27,11 @@ const appStore = {
|
||||||
// example,
|
// example,
|
||||||
applecalendar,
|
applecalendar,
|
||||||
caldavcalendar,
|
caldavcalendar,
|
||||||
closecomothercalendar,
|
closecom,
|
||||||
dailyvideo,
|
dailyvideo,
|
||||||
googlecalendar,
|
googlecalendar,
|
||||||
googlevideo,
|
googlevideo,
|
||||||
hubspotothercalendar,
|
hubspot,
|
||||||
huddle01video,
|
huddle01video,
|
||||||
jitsivideo,
|
jitsivideo,
|
||||||
larkcalendar,
|
larkcalendar,
|
||||||
|
|
|
@ -190,6 +190,7 @@ export const createEvent = async (
|
||||||
const uid: string = getUid(calEvent);
|
const uid: string = getUid(calEvent);
|
||||||
const calendar = getCalendar(credential);
|
const calendar = getCalendar(credential);
|
||||||
let success = true;
|
let success = true;
|
||||||
|
let calError: string | undefined = undefined;
|
||||||
|
|
||||||
// Check if the disabledNotes flag is set to true
|
// Check if the disabledNotes flag is set to true
|
||||||
if (calEvent.hideCalendarNotes) {
|
if (calEvent.hideCalendarNotes) {
|
||||||
|
@ -207,11 +208,13 @@ export const createEvent = async (
|
||||||
if (error?.code === 404) {
|
if (error?.code === 404) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
if (error?.calError) {
|
||||||
|
calError = error.calError;
|
||||||
|
}
|
||||||
log.error("createEvent failed", error, calEvent);
|
log.error("createEvent failed", error, calEvent);
|
||||||
// @TODO: This code will be off till we can investigate an error with it
|
// @TODO: This code will be off till we can investigate an error with it
|
||||||
//https://github.com/calcom/cal.com/issues/3949
|
//https://github.com/calcom/cal.com/issues/3949
|
||||||
// await sendBrokenIntegrationEmail(calEvent, "calendar");
|
// await sendBrokenIntegrationEmail(calEvent, "calendar");
|
||||||
https: log.error("createEvent failed", error, calEvent);
|
|
||||||
return undefined;
|
return undefined;
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -223,6 +226,8 @@ export const createEvent = async (
|
||||||
uid,
|
uid,
|
||||||
createdEvent: creationResult,
|
createdEvent: creationResult,
|
||||||
originalEvent: calEvent,
|
originalEvent: calEvent,
|
||||||
|
calError,
|
||||||
|
calWarnings: creationResult?.additionalInfo.calWarnings,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -235,6 +240,9 @@ export const updateEvent = async (
|
||||||
const uid = getUid(calEvent);
|
const uid = getUid(calEvent);
|
||||||
const calendar = getCalendar(credential);
|
const calendar = getCalendar(credential);
|
||||||
let success = false;
|
let success = false;
|
||||||
|
let calError: string | undefined = undefined;
|
||||||
|
let calWarnings: string[] | undefined = [];
|
||||||
|
|
||||||
if (bookingRefUid === "") {
|
if (bookingRefUid === "") {
|
||||||
log.error("updateEvent failed", "bookingRefUid is empty", calEvent, credential);
|
log.error("updateEvent failed", "bookingRefUid is empty", calEvent, credential);
|
||||||
}
|
}
|
||||||
|
@ -251,10 +259,19 @@ export const updateEvent = async (
|
||||||
// @see https://github.com/calcom/cal.com/issues/3949
|
// @see https://github.com/calcom/cal.com/issues/3949
|
||||||
// await sendBrokenIntegrationEmail(calEvent, "calendar");
|
// await sendBrokenIntegrationEmail(calEvent, "calendar");
|
||||||
log.error("updateEvent failed", e, calEvent);
|
log.error("updateEvent failed", e, calEvent);
|
||||||
|
if (e?.calError) {
|
||||||
|
calError = e.calError;
|
||||||
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
if (Array.isArray(updatedResult)) {
|
||||||
|
calWarnings = updatedResult.flatMap((res) => res.additionalInfo.calWarnings ?? []);
|
||||||
|
} else {
|
||||||
|
calWarnings = updatedResult?.additionalInfo.calWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appName: credential.appName,
|
appName: credential.appName,
|
||||||
type: credential.type,
|
type: credential.type,
|
||||||
|
@ -262,6 +279,8 @@ export const updateEvent = async (
|
||||||
uid,
|
uid,
|
||||||
updatedEvent: updatedResult,
|
updatedEvent: updatedResult,
|
||||||
originalEvent: calEvent,
|
originalEvent: calEvent,
|
||||||
|
calError,
|
||||||
|
calWarnings,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,22 @@ export const AppsStatus = (props: { calEvent: CalendarEvent; t: TFunction }) =>
|
||||||
{props.calEvent.appsStatus.map((status) => (
|
{props.calEvent.appsStatus.map((status) => (
|
||||||
<li key={status.type} style={{ fontWeight: 400 }}>
|
<li key={status.type} style={{ fontWeight: 400 }}>
|
||||||
{status.appName}{" "}
|
{status.appName}{" "}
|
||||||
{status.success >= 1 && `✅ ${status.success > 1 ? `(x${status.success})` : ""}`}{" "}
|
{status.success >= 1 && `✅ ${status.success > 1 ? `(x${status.success})` : ""}`}
|
||||||
|
{status.warnings && status.warnings.length >= 1 && (
|
||||||
|
<ul style={{ fontSize: "14px" }}>
|
||||||
|
{status.warnings.map((warning, i) => (
|
||||||
|
<li key={i}>{warning}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
{status.failures >= 1 && `❌ ${status.failures > 1 ? `(x${status.failures})` : ""}`}
|
{status.failures >= 1 && `❌ ${status.failures > 1 ? `(x${status.failures})` : ""}`}
|
||||||
|
{status.errors.length >= 1 && (
|
||||||
|
<ul>
|
||||||
|
{status.errors.map((error, i) => (
|
||||||
|
<li key={i}>{error}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -788,6 +788,8 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
||||||
type: app.type,
|
type: app.type,
|
||||||
success: app.success ? 1 : 0,
|
success: app.success ? 1 : 0,
|
||||||
failures: !app.success ? 1 : 0,
|
failures: !app.success ? 1 : 0,
|
||||||
|
errors: app.calError ? [app.calError] : [],
|
||||||
|
warnings: app.calWarnings,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (reqAppsStatus === undefined) {
|
if (reqAppsStatus === undefined) {
|
||||||
|
@ -803,6 +805,8 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) {
|
||||||
const calcAppsStatus = reqAppsStatus.concat(resultStatus).reduce((prev, curr) => {
|
const calcAppsStatus = reqAppsStatus.concat(resultStatus).reduce((prev, curr) => {
|
||||||
if (prev[curr.type]) {
|
if (prev[curr.type]) {
|
||||||
prev[curr.type].success += curr.success;
|
prev[curr.type].success += curr.success;
|
||||||
|
prev[curr.type].errors = prev[curr.type].errors.concat(curr.errors);
|
||||||
|
prev[curr.type].warnings = prev[curr.type].warnings?.concat(curr.warnings || []);
|
||||||
} else {
|
} else {
|
||||||
prev[curr.type] = curr;
|
prev[curr.type] = curr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,12 +78,15 @@ export const getAppsStatus = (calEvent: CalendarEvent) => {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return `\n${calEvent.attendees[0].language.translate("apps_status")}
|
return `\n${calEvent.attendees[0].language.translate("apps_status")}
|
||||||
\n${calEvent.appsStatus.map(
|
${calEvent.appsStatus.map((app) => {
|
||||||
(app) =>
|
return `\n- ${app.appName} ${
|
||||||
`\t${app.appName} ${app.success >= 1 && `✅ ${app.success > 1 ? `(x${app.success})` : ""}`} ${
|
app.success >= 1 ? `✅ ${app.success > 1 ? `(x${app.success})` : ""}` : ""
|
||||||
app.failures >= 1 && `❌ ${app.failures > 1 ? `(x${app.failures})` : ""}`
|
}${
|
||||||
}`
|
app.warnings && app.warnings.length >= 1 ? app.warnings.map((warning) => `\n - ${warning}`) : ""
|
||||||
)}
|
} ${app.failures && app.failures >= 1 ? `❌ ${app.failures > 1 ? `(x${app.failures})` : ""}` : ""} ${
|
||||||
|
app.errors && app.errors.length >= 1 ? app.errors.map((error) => `\n - ${error}`) : ""
|
||||||
|
}`;
|
||||||
|
})}
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ export function deriveAppDictKeyFromType(appType: string, dict: Record<string, u
|
||||||
return appTypeVariant2;
|
return appTypeVariant2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Deprecated?
|
||||||
// Transform as last resort removing all underscores, applies to `hubspot_other_calendar` to be `hubsporothercalendar`
|
// Transform as last resort removing all underscores, applies to `hubspot_other_calendar` to be `hubsporothercalendar`
|
||||||
// and `closecom_other_calendar` to be `closecomothercalendar`
|
// and `closecom_other_calendar` to be `closecomothercalendar`
|
||||||
const appTypeVariant3 = appType.replace(/_/g, "");
|
const appTypeVariant3 = appType.replace(/_/g, "");
|
||||||
|
|
|
@ -108,6 +108,12 @@
|
||||||
"slug": "sendgrid",
|
"slug": "sendgrid",
|
||||||
"type": "sendgrid_other_calendar"
|
"type": "sendgrid_other_calendar"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"dirName": "closecom",
|
||||||
|
"categories": ["other"],
|
||||||
|
"slug": "closecom",
|
||||||
|
"type": "closecom_other_calendar"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"dirName": "whatsapp",
|
"dirName": "whatsapp",
|
||||||
"categories": ["video"],
|
"categories": ["video"],
|
||||||
|
|
|
@ -233,13 +233,11 @@ export default async function main() {
|
||||||
await createApp("jitsi", "jitsivideo", ["video"], "jitsi_video");
|
await createApp("jitsi", "jitsivideo", ["video"], "jitsi_video");
|
||||||
// Other apps
|
// Other apps
|
||||||
if (process.env.HUBSPOT_CLIENT_ID && process.env.HUBSPOT_CLIENT_SECRET) {
|
if (process.env.HUBSPOT_CLIENT_ID && process.env.HUBSPOT_CLIENT_SECRET) {
|
||||||
await createApp("hubspot", "hubspotothercalendar", ["other"], "hubspot_other_calendar", {
|
await createApp("hubspot", "hubspot", ["other"], "hubspot_other_calendar", {
|
||||||
client_id: process.env.HUBSPOT_CLIENT_ID,
|
client_id: process.env.HUBSPOT_CLIENT_ID,
|
||||||
client_secret: process.env.HUBSPOT_CLIENT_SECRET,
|
client_secret: process.env.HUBSPOT_CLIENT_SECRET,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// No need to check if environment variable is present, the API Key is set up by the user, not the system
|
|
||||||
await createApp("closecom", "closecomothercalendar", ["other"], "closecom_other_calendar");
|
|
||||||
await createApp("wipe-my-cal", "wipemycalother", ["other"], "wipemycal_other");
|
await createApp("wipe-my-cal", "wipemycalother", ["other"], "wipemycal_other");
|
||||||
if (process.env.GIPHY_API_KEY) {
|
if (process.env.GIPHY_API_KEY) {
|
||||||
await createApp("giphy", "giphy", ["other"], "giphy_other", {
|
await createApp("giphy", "giphy", ["other"], "giphy_other", {
|
||||||
|
|
|
@ -161,6 +161,8 @@ export const extendedBookingCreateBody = bookingCreateBodySchema.merge(
|
||||||
success: z.number(),
|
success: z.number(),
|
||||||
failures: z.number(),
|
failures: z.number(),
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
|
errors: z.string().array(),
|
||||||
|
warnings: z.string().array().optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|
|
@ -39,6 +39,7 @@ export type EventBusyDetails = EventBusyDate & {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CalendarServiceType = typeof Calendar;
|
export type CalendarServiceType = typeof Calendar;
|
||||||
|
export type AdditionalInfo = Record<string, unknown> & { calWarnings?: string[] };
|
||||||
|
|
||||||
export type NewCalendarEventType = {
|
export type NewCalendarEventType = {
|
||||||
uid: string;
|
uid: string;
|
||||||
|
@ -46,7 +47,7 @@ export type NewCalendarEventType = {
|
||||||
type: string;
|
type: string;
|
||||||
password: string;
|
password: string;
|
||||||
url: string;
|
url: string;
|
||||||
additionalInfo: Record<string, unknown>;
|
additionalInfo: AdditionalInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CalendarEventType = {
|
export type CalendarEventType = {
|
||||||
|
@ -119,6 +120,8 @@ export type AppsStatus = {
|
||||||
type: typeof App["type"];
|
type: typeof App["type"];
|
||||||
success: number;
|
success: number;
|
||||||
failures: number;
|
failures: number;
|
||||||
|
errors: string[];
|
||||||
|
warnings?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// If modifying this interface, probably should update builders/calendarEvent files
|
// If modifying this interface, probably should update builders/calendarEvent files
|
||||||
|
|
|
@ -22,6 +22,8 @@ export interface EventResult<T> {
|
||||||
createdEvent?: T;
|
createdEvent?: T;
|
||||||
updatedEvent?: T | T[];
|
updatedEvent?: T | T[];
|
||||||
originalEvent: CalendarEvent;
|
originalEvent: CalendarEvent;
|
||||||
|
calError?: string;
|
||||||
|
calWarnings?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateUpdateResult {
|
export interface CreateUpdateResult {
|
||||||
|
|
|
@ -7222,16 +7222,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/node@*", "@types/node@16.9.1", "@types/node@>=8.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0":
|
"@types/node@*", "@types/node@16.9.1", "@types/node@>=8.1.0", "@types/node@^12.12.54", "@types/node@^12.12.6", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0":
|
||||||
version "16.9.1"
|
version "16.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708"
|
||||||
integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
|
integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
|
||||||
|
|
||||||
"@types/node@^12.12.54", "@types/node@^12.12.6":
|
|
||||||
version "12.20.55"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
|
|
||||||
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
|
|
||||||
|
|
||||||
"@types/nodemailer@^6.4.5":
|
"@types/nodemailer@^6.4.5":
|
||||||
version "6.4.5"
|
version "6.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.5.tgz#09011ac73259245475d1688e4ba101860567dc39"
|
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.5.tgz#09011ac73259245475d1688e4ba101860567dc39"
|
||||||
|
|