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>
This commit is contained in:
Omar López 2022-11-22 13:44:08 -07:00 committed by GitHub
parent 3854b9c58e
commit a94d51c4bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 108 additions and 58 deletions

View File

@ -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=""

View File

@ -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.

View File

@ -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",

View File

@ -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")),
}; };

View File

@ -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)) {

View File

@ -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;

View File

@ -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")),

View File

@ -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,

View File

@ -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"),

View File

@ -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.

View File

@ -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"],

View File

@ -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: {

View File

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -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.

View File

@ -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,

View File

@ -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 });
} }

View File

@ -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
); );

View File

@ -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

View File

@ -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.",

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -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,

View File

@ -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,
}; };
}; };

View File

@ -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>

View File

@ -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;
} }

View File

@ -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}`) : ""
}`;
})}
`; `;
}; };

View File

@ -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, "");

View File

@ -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"],

View File

@ -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", {

View File

@ -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(),

View File

@ -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

View File

@ -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 {

View File

@ -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"