Add Huddle01 integration (#1675)

* Add Huddle01 integration

* updated huddle01 locale strings

Co-authored-by: deepso <deeps.o7o8.y@gmail.com>
Co-authored-by: Bailey Pumfleet <pumfleet@hey.com>
This commit is contained in:
Rohan Gupta 2022-02-03 17:29:02 +05:30 committed by GitHub
parent acf8b83b1a
commit 64db8d1cd4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 142 additions and 6 deletions

View file

@ -153,6 +153,7 @@ const BookingPage = (props: BookingPageProps) => {
[LocationType.GoogleMeet]: "Google Meet",
[LocationType.Zoom]: "Zoom Video",
[LocationType.Daily]: "Daily.co Video",
[LocationType.Huddle01]: "Huddle01 Video",
};
const defaultValues = () => {

View file

@ -4,6 +4,7 @@ import merge from "lodash/merge";
import { v5 as uuidv5 } from "uuid";
import { FAKE_DAILY_CREDENTIAL } from "@lib/integrations/Daily/DailyVideoApiAdapter";
import { FAKE_HUDDLE_CREDENTIAL } from "@lib/integrations/Huddle01/Huddle01VideoApiAdapter";
import { createEvent, updateEvent } from "@lib/integrations/calendar/CalendarManager";
import { AdditionInformation, CalendarEvent } from "@lib/integrations/calendar/interfaces/Calendar";
import { LocationType } from "@lib/location";
@ -48,15 +49,20 @@ export const isDaily = (location: string): boolean => {
return location === "integrations:daily";
};
export const isHuddle01 = (location: string): boolean => {
return location === "integrations:huddle01";
};
export const isDedicatedIntegration = (location: string): boolean => {
return isZoom(location) || isDaily(location);
return isZoom(location) || isDaily(location) || isHuddle01(location);
};
export const getLocationRequestFromIntegration = (location: string) => {
if (
location === LocationType.GoogleMeet.valueOf() ||
location === LocationType.Zoom.valueOf() ||
location === LocationType.Daily.valueOf()
location === LocationType.Daily.valueOf() ||
location === LocationType.Huddle01.valueOf()
) {
const requestId = uuidv5(location, uuidv5.URL);
@ -108,6 +114,7 @@ export default class EventManager {
if (hasDailyIntegration) {
this.videoCredentials.push(FAKE_DAILY_CREDENTIAL);
}
this.videoCredentials.push(FAKE_HUDDLE_CREDENTIAL);
}
/**

View file

@ -14,6 +14,8 @@ export function getIntegrationName(name: string) {
return "Apple Calendar";
case "daily_video":
return "Daily";
case "huddle01_video":
return "Huddle01";
}
}

View file

@ -0,0 +1,48 @@
import { Credential } from "@prisma/client";
import { handleErrorsJson } from "@lib/errors";
import { PartialReference } from "@lib/events/EventManager";
import { randomString } from "@lib/random";
import { VideoApiAdapter, VideoCallData } from "@lib/videoClient";
export const FAKE_HUDDLE_CREDENTIAL: Credential = {
id: +new Date().getTime(),
type: "huddle01_video",
key: { apikey: randomString(12) },
userId: +new Date().getTime(),
};
const Huddle01VideoApiAdapter = (): VideoApiAdapter => {
return {
getAvailability: () => {
return Promise.resolve([]);
},
createMeeting: async (): Promise<VideoCallData> => {
const res = await fetch(
"https://wpss2zlpb9.execute-api.us-east-1.amazonaws.com/new-meeting?utmCampaign=cal.com&utmSource=partner&utmMedium=calendar"
);
const { url } = await handleErrorsJson(res);
return Promise.resolve({
type: "huddle01_video",
id: randomString(21),
password: "",
url,
});
},
deleteMeeting: async (): Promise<void> => {
Promise.resolve();
},
updateMeeting: (bookingRef: PartialReference): Promise<VideoCallData> => {
return Promise.resolve({
type: "huddle01_video",
id: bookingRef.meetingId as string,
password: bookingRef.meetingPassword as string,
url: bookingRef.meetingUrl as string,
});
},
};
};
export default Huddle01VideoApiAdapter;

View file

@ -23,6 +23,7 @@ export type Integration = {
| "caldav_calendar"
| "apple_calendar"
| "stripe_payment"
| "huddle01_video"
| "metamask_web3";
title: string;
imageSrc: string;
@ -63,6 +64,14 @@ export const ALL_INTEGRATIONS = [
description: "Video Conferencing",
variant: "conferencing",
},
{
installed: true,
type: "huddle01_video",
title: "Huddle01",
imageSrc: "integrations/huddle.svg",
description: "Video Conferencing",
variant: "conferencing",
},
{
installed: true,
type: "caldav_calendar",
@ -125,7 +134,10 @@ export type IntegrationMeta = ReturnType<typeof getIntegrations>;
export function hasIntegration(integrations: IntegrationMeta, type: string): boolean {
return !!integrations.find(
(i) => i.type === type && !!i.installed && (type === "daily_video" || i.credentials.length > 0)
(i) =>
i.type === type &&
!!i.installed &&
(type === "daily_video" || type === "huddle01_video" || i.credentials.length > 0)
);
}
export function hasIntegrationInstalled(type: Integration["type"]): boolean {

View file

@ -4,4 +4,5 @@ export enum LocationType {
GoogleMeet = "integrations:google:meet",
Zoom = "integrations:zoom",
Daily = "integrations:daily",
Huddle01 = "integrations:huddle01",
}

View file

@ -5,6 +5,7 @@ import { v5 as uuidv5 } from "uuid";
import { getUid } from "@lib/CalEventParser";
import { EventResult } from "@lib/events/EventManager";
import { PartialReference } from "@lib/events/EventManager";
import Huddle01VideoApiAdapter from "@lib/integrations/Huddle01/Huddle01VideoApiAdapter";
import logger from "@lib/logger";
import DailyVideoApiAdapter from "./integrations/Daily/DailyVideoApiAdapter";
@ -44,6 +45,9 @@ const getVideoAdapters = (withCredentials: Credential[]): VideoApiAdapter[] =>
case "daily_video":
acc.push(DailyVideoApiAdapter(cred));
break;
case "huddle01_video":
acc.push(Huddle01VideoApiAdapter());
break;
default:
break;
}

View file

@ -261,6 +261,8 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
return <p className="text-sm">{t("cal_provide_zoom_meeting_url")}</p>;
case LocationType.Daily:
return <p className="text-sm">{t("cal_provide_video_meeting_url")}</p>;
case LocationType.Huddle01:
return <p className="text-sm">{t("cal_provide_huddle01_meeting_url")}</p>;
default:
return null;
}
@ -420,6 +422,34 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
<span className="ltr:ml-2 rtl:mr-2text-sm">Google Meet</span>
</div>
)}
{location.type === LocationType.Huddle01 && (
<div className="flex items-center flex-grow">
<svg
width="1.25em"
height="1.25em"
viewBox="0 0 26 18"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M14.8607 0H4.04353C3.16693 0 2.32622 0.347292 1.70636 0.965476C1.08651 1.58366 0.738281 2.4221 0.738281 3.29634V14.0844C0.738281 14.9586 1.08651 15.7971 1.70636 16.4152C2.32622 17.0334 3.16693 17.3807 4.04353 17.3807H14.8607C15.7373 17.3807 16.578 17.0334 17.1979 16.4152C17.8177 15.7971 18.166 14.9586 18.166 14.0844V3.29634C18.166 2.4221 17.8177 1.58366 17.1979 0.965476C16.578 0.347292 15.7373 0 14.8607 0V0Z"
fill="#246BFD"
/>
<path
d="M24.1641 3.10754C24.0122 3.14004 23.8679 3.20106 23.7389 3.28734L21.1623 4.85161C20.7585 5.09889 20.4269 5.44766 20.2008 5.86299C19.9686 6.28713 19.8472 6.76272 19.8477 7.24595V10.1407C19.8475 10.6251 19.9694 11.1017 20.2023 11.5267C20.4295 11.9431 20.7627 12.2925 21.1683 12.5396L23.7645 14.1038C23.9325 14.2074 24.1202 14.2753 24.3158 14.3031C24.5103 14.3302 24.7084 14.3164 24.8973 14.2627C25.0881 14.2077 25.2659 14.1149 25.4201 13.99C25.5764 13.862 25.706 13.7047 25.8017 13.527C25.9321 13.2836 26.0003 13.0118 26 12.7359V4.62985C25.9995 4.39497 25.9483 4.16296 25.8498 3.94961C25.7523 3.73989 25.6097 3.55418 25.4321 3.40571C25.258 3.26046 25.0522 3.15784 24.8311 3.10604C24.6118 3.05359 24.3832 3.0541 24.1641 3.10754Z"
fill="#246BFD"
/>
<path
d="M7.07325 14.3165C6.26596 14.3165 5.64849 14.0822 5.22081 13.6138C4.79313 13.1453 4.57928 12.484 4.57928 11.63V6.0112C4.57928 5.15515 4.79313 4.49338 5.22081 4.0259C5.64849 3.55842 6.26596 3.32418 7.07325 3.32318C7.87452 3.32318 8.4915 3.55742 8.92419 4.0259C9.35687 4.49438 9.57071 5.15615 9.5657 6.0112V11.63C9.5657 12.484 9.35186 13.1453 8.92419 13.6138C8.49651 14.0822 7.87953 14.3165 7.07325 14.3165ZM7.07325 12.7897C7.63914 12.7897 7.92259 12.4401 7.9236 11.7408V5.90332C7.9236 5.20409 7.64015 4.85448 7.07325 4.85448C6.50635 4.85448 6.2224 5.20409 6.2214 5.90332V11.7363C6.2214 12.4396 6.50534 12.7907 7.07325 12.7897Z"
fill="white"
/>
<path
d="M12.6791 6.0112H10.9619V4.82002C11.3388 4.83087 11.7155 4.78952 12.0811 4.69716C12.3452 4.63341 12.5856 4.49564 12.7737 4.3001C12.9727 4.05484 13.1254 3.77563 13.2244 3.47601H14.3287V14.1637H12.6791V6.0112Z"
fill="white"
/>
</svg>
<span className="ml-2 text-sm">Huddle01 Web3 Video</span>
</div>
)}
{location.type === LocationType.Daily && (
<div className="flex flex-grow">
<svg
@ -1559,6 +1589,9 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
if (hasIntegration(integrations, "daily_video")) {
locationOptions.push({ value: LocationType.Daily, label: "Daily.co Video" });
}
if (hasIntegration(integrations, "huddle01_video")) {
locationOptions.push({ value: LocationType.Huddle01, label: "Huddle01 Video" });
}
const currency =
(credentials.find((integration) => integration.type === "stripe_payment")?.key as unknown as StripeData)
?.default_currency || "usd";

View file

@ -480,7 +480,7 @@ function ConnectOrDisconnectIntegrationButton(props: {
);
}
/** We don't need to "Connect", just show that it's installed */
if (props.type === "daily_video") {
if (props.type === "daily_video" || props.type === "huddle01_video") {
return (
<div className="px-3 py-2 truncate">
<h3 className="text-sm font-medium text-gray-700">{t("installed")}</h3>

View file

@ -0,0 +1,14 @@
<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M14.8607 0H4.04353C3.16693 0 2.32622 0.347292 1.70636 0.965476C1.08651 1.58366 0.738281 2.4221 0.738281 3.29634V14.0844C0.738281 14.9586 1.08651 15.7971 1.70636 16.4152C2.32622 17.0334 3.16693 17.3807 4.04353 17.3807H14.8607C15.7373 17.3807 16.578 17.0334 17.1979 16.4152C17.8177 15.7971 18.166 14.9586 18.166 14.0844V3.29634C18.166 2.4221 17.8177 1.58366 17.1979 0.965476C16.578 0.347292 15.7373 0 14.8607 0V0Z"
fill="#246BFD" />
<path
d="M24.1641 3.10754C24.0122 3.14004 23.8679 3.20106 23.7389 3.28734L21.1623 4.85161C20.7585 5.09889 20.4269 5.44766 20.2008 5.86299C19.9686 6.28713 19.8472 6.76272 19.8477 7.24595V10.1407C19.8475 10.6251 19.9694 11.1017 20.2023 11.5267C20.4295 11.9431 20.7627 12.2925 21.1683 12.5396L23.7645 14.1038C23.9325 14.2074 24.1202 14.2753 24.3158 14.3031C24.5103 14.3302 24.7084 14.3164 24.8973 14.2627C25.0881 14.2077 25.2659 14.1149 25.4201 13.99C25.5764 13.862 25.706 13.7047 25.8017 13.527C25.9321 13.2836 26.0003 13.0118 26 12.7359V4.62985C25.9995 4.39497 25.9483 4.16296 25.8498 3.94961C25.7523 3.73989 25.6097 3.55418 25.4321 3.40571C25.258 3.26046 25.0522 3.15784 24.8311 3.10604C24.6118 3.05359 24.3832 3.0541 24.1641 3.10754Z"
fill="#246BFD" />
<path
d="M7.07325 14.3165C6.26596 14.3165 5.64849 14.0822 5.22081 13.6138C4.79313 13.1453 4.57928 12.484 4.57928 11.63V6.0112C4.57928 5.15515 4.79313 4.49338 5.22081 4.0259C5.64849 3.55842 6.26596 3.32418 7.07325 3.32318C7.87452 3.32318 8.4915 3.55742 8.92419 4.0259C9.35687 4.49438 9.57071 5.15615 9.5657 6.0112V11.63C9.5657 12.484 9.35186 13.1453 8.92419 13.6138C8.49651 14.0822 7.87953 14.3165 7.07325 14.3165ZM7.07325 12.7897C7.63914 12.7897 7.92259 12.4401 7.9236 11.7408V5.90332C7.9236 5.20409 7.64015 4.85448 7.07325 4.85448C6.50635 4.85448 6.2224 5.20409 6.2214 5.90332V11.7363C6.2214 12.4396 6.50534 12.7907 7.07325 12.7897Z"
fill="white" />
<path
d="M12.6791 6.0112H10.9619V4.82002C11.3388 4.83087 11.7155 4.78952 12.0811 4.69716C12.3452 4.63341 12.5856 4.49564 12.7737 4.3001C12.9727 4.05484 13.1254 3.77563 13.2244 3.47601H14.3287V14.1637H12.6791V6.0112Z"
fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -536,6 +536,7 @@
"cal_provide_google_meet_location": "Cal wird einen Google Meet Termin zur Verfügung stellen.",
"cal_provide_zoom_meeting_url": "Cal stellt eine Zoom Meeting-URL zur Verfügung.",
"cal_provide_video_meeting_url": "Cal stellt eine tägliche Video-Meeting-URL zur Verfügung.",
"cal_provide_huddle01_meeting_url": "Cal stellt eine tägliche Huddle01-Web3-Meeting-URL zur Verfügung.",
"require_payment": "Zahlung erforderlich",
"commission_per_transaction": "Provision pro Transaktion",
"event_type_updated_successfully_description": "Ihr Ereignistyp wurde erfolgreich aktualisiert.",

View file

@ -536,6 +536,7 @@
"cal_provide_google_meet_location": "Cal will provide a Google Meet location.",
"cal_provide_zoom_meeting_url": "Cal will provide a Zoom meeting URL.",
"cal_provide_video_meeting_url": "Cal will provide a Daily video meeting URL.",
"cal_provide_huddle01_meeting_url": "Cal will provide a Huddle01 web3 video meeting URL.",
"require_payment": "Require Payment",
"commission_per_transaction": "commission per transaction",
"event_type_updated_successfully_description": "Your event type has been updated successfully.",

View file

@ -524,6 +524,7 @@
"cal_provide_google_meet_location": "Cal proporcionará una URL de reunión de Google Meet.",
"cal_provide_zoom_meeting_url": "Cal proporcionará una URL de reunión de Zoom.",
"cal_provide_video_meeting_url": "Cal proporcionará una URL de reunión de Daily Video.",
"cal_provide_huddle01_meeting_url": "Cal proporcionará una URL de reunión de Huddle01 Web3 Video.",
"require_payment": "Requiere Pago",
"commission_per_transaction": "Comisión por Transacción",
"event_type_updated_successfully_description": "Tu Evento fue Actualizado con Éxito.",

View file

@ -490,6 +490,7 @@
"cal_provide_google_meet_location": "Cal fournira un lien Google Meet.",
"cal_provide_zoom_meeting_url": "Cal fournira une URL de réunion Zoom.",
"cal_provide_video_meeting_url": "Cal fournira une URL de réunion Daily video.",
"cal_provide_huddle01_meeting_url": "Cal fournira une URL de réunion Huddle01 web3 video.",
"require_payment": "Exiger un paiement",
"commission_per_transaction": "commission par transaction",
"event_type_updated_successfully_description": "Votre type d'événement a été mis à jour avec succès.",

View file

@ -515,7 +515,8 @@
"cal_invitee_phone_number_scheduling": "Cal chiederà al tuo invitato di inserire un numero di telefono prima della pianificazione.",
"cal_provide_google_meet_location": "Cal fornirà un Google Meet location.",
"cal_provide_zoom_meeting_url": "Cal fornirà un URL di riunione Zoom.",
"cal_provide_video_meeting_url": "Cal fornirà un URL di riunione Zoom.",
"cal_provide_video_meeting_url": "Cal fornirà un URL di riunione Daily video.",
"cal_provide_huddle01_meeting_url": "Cal fornirà un URL di riunione Huddle01 web3 video.",
"require_payment": "Richiedi Pagamento",
"commission_per_transaction": "commissione per transazione",
"event_type_updated_successfully_description": "Il tuo team è stato aggiornato con successo.",

View file

@ -488,6 +488,7 @@
"cal_provide_google_meet_location": "CalはGoogleMeetの場所を提供します。",
"cal_provide_zoom_meeting_url": "カルはZoomミーティングURLを提供します。",
"cal_provide_video_meeting_url": "カルは毎日のビデオミーティングのURLを提供します。",
"cal_provide_huddle01_meeting_url": "カルはHuddle01 Web3ミーティングURLを提供します。",
"require_payment": "お支払いが必要です",
"commission_per_transaction": "取引あたりの手数料",
"event_type_updated_successfully_description": "イベント種別の更新が完了しました。",

View file

@ -511,6 +511,7 @@
"cal_provide_google_meet_location": "Cal은 Google Meet 위치를 제공합니다.",
"cal_provide_zoom_meeting_url": "Cal은 Zoom 회의 URL을 제공합니다.",
"cal_provide_video_meeting_url": "Cal은 일일 화상 회의 URL을 제공합니다.",
"cal_provide_huddle01_meeting_url": "Cal은 Huddle01 Web3 회의 URL을 제공합니다.",
"require_payment": "지불 요청",
"commission_per_transaction": "거래당 수수료",
"event_type_updated_successfully_description": "이벤트 타입이 성공적으로 업데이트되었습니다.",

View file

@ -481,6 +481,7 @@
"cal_provide_google_meet_location": "Cal zal een Google Meet meeting-URL meegeven in de afspraak bevestiging.",
"cal_provide_zoom_meeting_url": "Cal zal een Zoom meeting-URL meegeven in de afspraak bevestiging.",
"cal_provide_video_meeting_url": "Cal zal een Daily meeting-URL meegeven in de afspraak bevestiging.",
"cal_provide_huddle01_meeting_url": "Cal zal een Huddle01 web3 meeting-URL meegeven in de afspraak bevestiging.",
"require_payment": "Betaling vereisen",
"commission_per_transaction": "commissie per transactie",
"event_type_updated_successfully_description": "Uw evenement is met succes bijgewerkt.",

View file

@ -527,6 +527,7 @@
"cal_provide_google_meet_location": "Cal zapewni lokalizację Google Meet.",
"cal_provide_zoom_meeting_url": "Cal zapewni URL spotkania Zoom.",
"cal_provide_video_meeting_url": "Kal poda adres URL spotkania wideo platformy Daily.",
"cal_provide_huddle01_meeting_url": "Cal zapewni URL spotkania Huddle01 Web3.",
"require_payment": "Wymagaj płatności",
"commission_per_transaction": "prowizja za transakcję",
"event_type_updated_successfully_description": "Twój typ wydarzenia został pomyślnie zaktualizowany.",

View file

@ -527,6 +527,7 @@
"cal_provide_google_meet_location": "Cal fornecerá um link para o Google Meet.",
"cal_provide_zoom_meeting_url": "Cal fornecerá uma URL de reunião do Zoom.",
"cal_provide_video_meeting_url": "O Cal irá fornecer um URL de reunião do Daily video.",
"cal_provide_huddle01_meeting_url": "O Cal irá fornecer um URL de reunião do Huddle01 Web3 video.",
"require_payment": "Requerer Pagamento",
"commission_per_transaction": "comissão por transação",
"event_type_updated_successfully_description": "O seu tipo de evento foi atualizado com sucesso.",

View file

@ -536,6 +536,7 @@
"cal_provide_google_meet_location": "Cal fornecerá um local para o Google Meet.",
"cal_provide_zoom_meeting_url": "Cal fornecerá uma URL de reunião Zoom .",
"cal_provide_video_meeting_url": "O Cal irá fornecer um URL de reunião do Daily video.",
"cal_provide_huddle01_meeting_url": "O Cal irá fornecer um URL de reunião do Huddle01 Web3 video.",
"require_payment": "Requer Pagamento",
"commission_per_transaction": "comissão por transação",
"event_type_updated_successfully_description": "O seu tipo de evento foi atualizado com sucesso.",

View file

@ -487,7 +487,8 @@
"cal_invitee_phone_number_scheduling": "Cal va cere invitatului dvs. să introducă un număr de telefon înainte de programare.",
"cal_provide_google_meet_location": "Cal va oferi o locație Google Meet.",
"cal_provide_zoom_meeting_url": "Cal va oferi un URL pentru ședința de Zoom.",
"cal_provide_video_meeting_url": "Cal va oferi un URL pentru ședința de Zoom.",
"cal_provide_video_meeting_url": "Cal va oferi un URL pentru ședința de Daily.",
"cal_provide_huddle01_meeting_url": "Cal va oferi un URL pentru ședința de Huddle01 Web3.",
"require_payment": "Solicită plata",
"commission_per_transaction": "comision per tranzacție",
"event_type_updated_successfully_description": "Tipul de eveniment a fost actualizat cu succes.",

View file

@ -528,6 +528,7 @@
"cal_provide_google_meet_location": "Cal создаст ссылку на встречу в Google Meet.",
"cal_provide_zoom_meeting_url": "Cal создаст ссылку на встречу в Zoom.",
"cal_provide_video_meeting_url": "Cal создаст ссылку на встречу в Daily.",
"cal_provide_huddle01_meeting_url": "Cal создаст ссылку на встречу в Huddle01 Web3.",
"require_payment": "Требуется оплата",
"commission_per_transaction": "комиссия за сделку",
"event_type_updated_successfully_description": "Ваш шаблон события успешно обновлён.",

View file

@ -534,6 +534,7 @@
"cal_provide_google_meet_location": "Cal 将提供 Google Meet 位置。",
"cal_provide_zoom_meeting_url": "Cal 将提供Zoom会议 URL",
"cal_provide_video_meeting_url": "Cal 将提供Daily视频会议 URL",
"cal_provide_huddle01_meeting_url": "Cal 将提供Huddle01 Web3视频会议 URL",
"require_payment": "需要付款",
"commission_per_transaction": "每笔交易的佣金",
"event_type_updated_successfully_description": "您的事件类型更新成功。",