feat: added office 365 video to conferencing atoms (#18067)
* feat: added office 365 video to conferencing atoms * added documentation for conferencing atoms * added props table to the documentation --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { ConferencingController } from "@/modules/conferencing/controllers/confe
|
||||
import { ConferencingRepository } from "@/modules/conferencing/repositories/conferencing.respository";
|
||||
import { ConferencingService } from "@/modules/conferencing/services/conferencing.service";
|
||||
import { GoogleMeetService } from "@/modules/conferencing/services/google-meet.service";
|
||||
import { Office365VideoService } from "@/modules/conferencing/services/office365-video.service";
|
||||
import { ZoomVideoService } from "@/modules/conferencing/services/zoom-video.service";
|
||||
import { CredentialsRepository } from "@/modules/credentials/credentials.repository";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
@@ -21,6 +22,7 @@ import { ConfigModule } from "@nestjs/config";
|
||||
UsersRepository,
|
||||
TokensRepository,
|
||||
ZoomVideoService,
|
||||
Office365VideoService,
|
||||
AppsRepository,
|
||||
],
|
||||
exports: [],
|
||||
|
||||
@@ -15,6 +15,7 @@ import { GetDefaultConferencingAppOutputResponseDto } from "@/modules/conferenci
|
||||
import { SetDefaultConferencingAppOutputResponseDto } from "@/modules/conferencing/outputs/set-default-conferencing-app.output";
|
||||
import { ConferencingService } from "@/modules/conferencing/services/conferencing.service";
|
||||
import { GoogleMeetService } from "@/modules/conferencing/services/google-meet.service";
|
||||
import { Office365VideoService } from "@/modules/conferencing/services/office365-video.service";
|
||||
import { ZoomVideoService } from "@/modules/conferencing/services/zoom-video.service";
|
||||
import { TokensRepository } from "@/modules/tokens/tokens.repository";
|
||||
import { UserWithProfile } from "@/modules/users/users.repository";
|
||||
@@ -39,7 +40,7 @@ import { ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
|
||||
import { plainToInstance } from "class-transformer";
|
||||
import { Request } from "express";
|
||||
|
||||
import { GOOGLE_MEET, ZOOM, SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import { GOOGLE_MEET, ZOOM, SUCCESS_STATUS, OFFICE_365_VIDEO } from "@calcom/platform-constants";
|
||||
|
||||
export type OAuthCallbackState = {
|
||||
accessToken: string;
|
||||
@@ -61,7 +62,8 @@ export class ConferencingController {
|
||||
private readonly tokensRepository: TokensRepository,
|
||||
private readonly conferencingService: ConferencingService,
|
||||
private readonly googleMeetService: GoogleMeetService,
|
||||
private readonly zoomVideoService: ZoomVideoService
|
||||
private readonly zoomVideoService: ZoomVideoService,
|
||||
private readonly office365VideoService: Office365VideoService
|
||||
) {}
|
||||
|
||||
@Post("/:app/connect")
|
||||
@@ -116,8 +118,18 @@ export class ConferencingController {
|
||||
data: plainToInstance(ConferencingAppsOauthUrlOutputDto, credential),
|
||||
};
|
||||
|
||||
case OFFICE_365_VIDEO:
|
||||
credential = await this.office365VideoService.generateOffice365AuthUrl(JSON.stringify(state));
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: plainToInstance(ConferencingAppsOauthUrlOutputDto, credential),
|
||||
};
|
||||
|
||||
default:
|
||||
throw new BadRequestException("Invalid conferencing app, available apps are: ", [ZOOM].join(", "));
|
||||
throw new BadRequestException(
|
||||
"Invalid conferencing app, available apps are: ",
|
||||
[ZOOM, OFFICE_365_VIDEO].join(", ")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,8 +159,14 @@ export class ConferencingController {
|
||||
case ZOOM:
|
||||
return await this.zoomVideoService.connectZoomApp(decodedCallbackState, code, userId);
|
||||
|
||||
case OFFICE_365_VIDEO:
|
||||
return await this.office365VideoService.connectOffice365App(decodedCallbackState, code, userId);
|
||||
|
||||
default:
|
||||
throw new BadRequestException("Invalid conferencing app, available apps are: ", [ZOOM].join(", "));
|
||||
throw new BadRequestException(
|
||||
"Invalid conferencing app, available apps are: ",
|
||||
[ZOOM, OFFICE_365_VIDEO].join(", ")
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import { AppsRepository } from "@/modules/apps/apps.repository";
|
||||
import { OAuthCallbackState } from "@/modules/conferencing/controllers/conferencing.controller";
|
||||
import { BadRequestException, Logger, NotFoundException } from "@nestjs/common";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { z } from "zod";
|
||||
|
||||
import { OFFICE_365_VIDEO, OFFICE_365_VIDEO_TYPE } from "@calcom/platform-constants";
|
||||
|
||||
import stringify = require("qs-stringify");
|
||||
|
||||
const zoomAppKeysSchema = z.object({
|
||||
client_id: z.string(),
|
||||
client_secret: z.string(),
|
||||
});
|
||||
|
||||
@Injectable()
|
||||
export class Office365VideoService {
|
||||
private logger = new Logger("Office365VideoService");
|
||||
private redirectUri = `${this.config.get("api.url")}/conferencing/${OFFICE_365_VIDEO}/oauth/callback`;
|
||||
private scopes = ["OnlineMeetings.ReadWrite", "offline_access"];
|
||||
|
||||
constructor(private readonly config: ConfigService, private readonly appsRepository: AppsRepository) {}
|
||||
|
||||
async getOffice365AppKeys() {
|
||||
const app = await this.appsRepository.getAppBySlug(OFFICE_365_VIDEO);
|
||||
|
||||
const { client_id, client_secret } = zoomAppKeysSchema.parse(app?.keys);
|
||||
|
||||
if (!client_id) {
|
||||
throw new NotFoundException("Office365 app not found");
|
||||
}
|
||||
|
||||
if (!client_secret) {
|
||||
throw new NotFoundException("Office365 app not found");
|
||||
}
|
||||
|
||||
return { client_id, client_secret };
|
||||
}
|
||||
|
||||
async generateOffice365AuthUrl(state: string) {
|
||||
const { client_id } = await this.getOffice365AppKeys();
|
||||
|
||||
const params = {
|
||||
response_type: "code",
|
||||
client_id,
|
||||
scope: this.scopes.join(" "),
|
||||
redirect_uri: this.redirectUri,
|
||||
state: state,
|
||||
};
|
||||
|
||||
const query = stringify(params);
|
||||
|
||||
const url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?${query}`;
|
||||
return { url };
|
||||
}
|
||||
|
||||
async connectOffice365App(state: OAuthCallbackState, code: string, userId: number) {
|
||||
const { client_id, client_secret } = await this.getOffice365AppKeys();
|
||||
|
||||
const toUrlEncoded = (payload: Record<string, string>) =>
|
||||
Object.keys(payload)
|
||||
.map((key) => `${key}=${encodeURIComponent(payload[key])}`)
|
||||
.join("&");
|
||||
|
||||
const body = toUrlEncoded({
|
||||
client_id,
|
||||
grant_type: "authorization_code",
|
||||
code,
|
||||
scope: this.scopes.join(" "),
|
||||
redirect_uri: this.redirectUri,
|
||||
client_secret,
|
||||
});
|
||||
|
||||
const response = await fetch("https://login.microsoftonline.com/common/oauth2/v2.0/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
||||
},
|
||||
body,
|
||||
});
|
||||
|
||||
const responseBody = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new BadRequestException(responseBody.error);
|
||||
}
|
||||
|
||||
const whoami = await fetch("https://graph.microsoft.com/v1.0/me", {
|
||||
headers: { Authorization: `Bearer ${responseBody.access_token}` },
|
||||
});
|
||||
|
||||
const graphUser = await whoami.json();
|
||||
|
||||
// In some cases, graphUser.mail is null. Then graphUser.userPrincipalName most likely contains the email address.
|
||||
responseBody.email = graphUser.mail ?? graphUser.userPrincipalName;
|
||||
responseBody.expiry_date = Math.round(+new Date() / 1000 + responseBody.expires_in); // set expiry date in seconds
|
||||
delete responseBody.expires_in;
|
||||
|
||||
const existingCredentialOffice365Video = await this.appsRepository.findAppCredential({
|
||||
type: OFFICE_365_VIDEO_TYPE,
|
||||
userId,
|
||||
appId: OFFICE_365_VIDEO,
|
||||
});
|
||||
|
||||
const credentialIdsToDelete = existingCredentialOffice365Video.map((item) => item.id);
|
||||
if (credentialIdsToDelete.length > 0) {
|
||||
await this.appsRepository.deleteAppCredentials(credentialIdsToDelete, userId);
|
||||
}
|
||||
|
||||
await this.appsRepository.createAppCredential(
|
||||
OFFICE_365_VIDEO_TYPE,
|
||||
responseBody as unknown as Prisma.InputJsonObject,
|
||||
userId,
|
||||
OFFICE_365_VIDEO
|
||||
);
|
||||
|
||||
return { url: state.returnTo ?? "" };
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ const zoomAppKeysSchema = z.object({
|
||||
@Injectable()
|
||||
export class ZoomVideoService {
|
||||
private logger = new Logger("ZoomVideoService");
|
||||
private redirectUri = `${this.config.get("api.url")}/conferencing/zoom/oauth/callback`;
|
||||
private redirectUri = `${this.config.get("api.url")}/conferencing/${ZOOM}/oauth/callback`;
|
||||
|
||||
constructor(private readonly config: ConfigService, private readonly appsRepository: AppsRepository) {}
|
||||
|
||||
|
||||
@@ -15367,4 +15367,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2878,6 +2878,7 @@
|
||||
"salesforce_ignore_guests": "Do not create new records for guests added to the booking",
|
||||
"google_meet": "Google Meet",
|
||||
"zoom": "Zoom",
|
||||
"office_365_video": "MS Teams Video",
|
||||
"lock_attribute_for_assignment": "Lock for assignment",
|
||||
"lock_attribute_for_assignment_description": "Locking would only allow assignments from Directory Sync",
|
||||
"attribute_edited_successfully": "Attribute edited successfully",
|
||||
|
||||
+2
-1
@@ -197,7 +197,8 @@
|
||||
"platform/atoms/booker",
|
||||
"platform/atoms/event-type",
|
||||
"platform/atoms/calendar-settings",
|
||||
"platform/atoms/payment-form"
|
||||
"platform/atoms/payment-form",
|
||||
"platform/atoms/conferencing-apps"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: "Conferencing Apps"
|
||||
---
|
||||
|
||||
The Conferencing Apps Atom allows users to seamlessly install applications such as Zoom, Google Meet, and Microsoft Teams, enabling them to set these as default or optional locations for their events.
|
||||
|
||||
Below code snippet can be used to render Conferencing Apps Atom
|
||||
|
||||
```js
|
||||
|
||||
import { ConferencingAppsSettings } from "@calcom/atoms";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
export default function ConferencingApps() {
|
||||
const pathname = usePathname();
|
||||
const callbackUri = `${window.location.origin}${pathname}`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConferencingAppsSettings returnTo={callbackUri} onErrorReturnTo={callbackUri} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Below is a list of props that can be passed to the Conferencing Apps Atom
|
||||
|
||||
<p></p>
|
||||
|
||||
| Name | Required | Description |
|
||||
| :------------------ | :------- | :-------------------------------------------------------------------------- |
|
||||
| returnTo | No | The URL of the page to redirect to after a successful installation. |
|
||||
| onErrorReturnTo | No | The URL of the page to redirect to in case an error occurs. |
|
||||
| disableToasts | No | boolean value to disable toast notifications in the atom. |
|
||||
|
||||
|
||||
## Google Meet
|
||||
|
||||
For a demonstration of installing Google Meet, setting it as the default conferencing app for all event types, and removing the app, please watch the video below.
|
||||
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/b12957f8588843669dbe2c30aef18575?sid=c42c5643-a319-41bb-bcb4-236c9df7ebd4"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen="true"
|
||||
></iframe>
|
||||
|
||||
<p></p>
|
||||
|
||||
<Info>Google meet requires Google Calendar to be installed first</Info>
|
||||
|
||||
## Zoom
|
||||
|
||||
For a demonstration of installing Zoom, setting it as the default conferencing app for all event types, and removing the app, please watch the video below.
|
||||
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/b423af66770b4645b0b79cfaebda8869?sid=c7578b79-717a-4092-a112-2804aa2001a8"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen="true"
|
||||
></iframe>
|
||||
|
||||
<p></p>
|
||||
|
||||
## MS Teams Video
|
||||
|
||||
For a demonstration of installing MS Teams Video, setting it as the default conferencing app for all event types, and removing the app, please watch the video below.
|
||||
|
||||
<p></p>
|
||||
|
||||
<iframe
|
||||
height="315"
|
||||
style={{ width: "100%", maxWidth: "560px" }}
|
||||
src="https://www.loom.com/embed/2828f1d52c7d48889ac5c9a5055bd040?sid=a5ce1cb5-4000-4b4b-94bd-45d23c247a2b"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen="true"
|
||||
></iframe>
|
||||
|
||||
<p></p>
|
||||
|
||||
<Info>
|
||||
Connecting with MS Teams requires a work/school Microsoft account.
|
||||
If you continue with a personal account you will receive an error
|
||||
</Info>
|
||||
@@ -1,14 +1,12 @@
|
||||
import { AppOnboardingSteps } from "@calcom/lib/apps/appOnboardingSteps";
|
||||
import { getAppOnboardingUrl } from "@calcom/lib/apps/getAppOnboardingUrl";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import type { DialogProps } from "@calcom/ui";
|
||||
import { Button } from "@calcom/ui";
|
||||
import { Dialog, DialogClose, DialogContent, DialogFooter } from "@calcom/ui";
|
||||
|
||||
import useAddAppMutation from "../../_utils/useAddAppMutation";
|
||||
|
||||
export function AccountDialog(props: DialogProps) {
|
||||
const mutation = useAddAppMutation(null);
|
||||
export function AccountDialog(
|
||||
props: DialogProps & {
|
||||
handleSubmit: () => void;
|
||||
}
|
||||
) {
|
||||
return (
|
||||
<Dialog name="Account check" open={props.open} onOpenChange={props.onOpenChange}>
|
||||
<DialogContent
|
||||
@@ -27,21 +25,7 @@ export function AccountDialog(props: DialogProps) {
|
||||
Cancel
|
||||
</DialogClose>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
mutation.mutate({
|
||||
type: "office365_video",
|
||||
variant: "conferencing",
|
||||
slug: "msteams",
|
||||
returnTo:
|
||||
WEBAPP_URL +
|
||||
getAppOnboardingUrl({
|
||||
slug: "msteams",
|
||||
step: AppOnboardingSteps.EVENT_TYPES_STEP,
|
||||
}),
|
||||
})
|
||||
}>
|
||||
<Button type="button" onClick={props.handleSubmit}>
|
||||
Continue
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -1,10 +1,29 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { AppOnboardingSteps } from "@calcom/lib/apps/appOnboardingSteps";
|
||||
import { getAppOnboardingUrl } from "@calcom/lib/apps/getAppOnboardingUrl";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
|
||||
import useAddAppMutation from "../../_utils/useAddAppMutation";
|
||||
import type { InstallAppButtonProps } from "../../types";
|
||||
import AddIntegration from "./AccountDialog";
|
||||
import AccountDialog from "./AccountDialog";
|
||||
|
||||
export default function InstallAppButton(props: InstallAppButtonProps) {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const mutation = useAddAppMutation(null);
|
||||
const handleSubmit = () => {
|
||||
mutation.mutate({
|
||||
type: "office365_video",
|
||||
variant: "conferencing",
|
||||
slug: "msteams",
|
||||
returnTo:
|
||||
WEBAPP_URL +
|
||||
getAppOnboardingUrl({
|
||||
slug: "msteams",
|
||||
step: AppOnboardingSteps.EVENT_TYPES_STEP,
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -14,7 +33,7 @@ export default function InstallAppButton(props: InstallAppButtonProps) {
|
||||
},
|
||||
disabled: isModalOpen,
|
||||
})}
|
||||
<AddIntegration open={isModalOpen} onOpenChange={setIsModalOpen} />
|
||||
<AccountDialog open={isModalOpen} onOpenChange={setIsModalOpen} handleSubmit={handleSubmit} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
+19
-2
@@ -1,13 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useReducer } from "react";
|
||||
import { useReducer, useState } from "react";
|
||||
|
||||
import AccountDialog from "@calcom/app-store/office365video/components/AccountDialog";
|
||||
import { AppList } from "@calcom/features/apps/components/AppList";
|
||||
import DisconnectIntegrationModal from "@calcom/features/apps/components/DisconnectIntegrationModal";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { GOOGLE_MEET, ZOOM } from "@calcom/platform-constants";
|
||||
import { GOOGLE_MEET, OFFICE_365_VIDEO, ZOOM } from "@calcom/platform-constants";
|
||||
import { QueryCell } from "@calcom/trpc/components/QueryCell";
|
||||
import type { App } from "@calcom/types/App";
|
||||
import {
|
||||
@@ -91,6 +92,8 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
}
|
||||
);
|
||||
|
||||
const [isAccountModalOpen, setIsAccountModalOpen] = useState(false);
|
||||
|
||||
const handleModelClose = () => {
|
||||
updateModal({ isOpen: false, credentialId: null, app: null });
|
||||
};
|
||||
@@ -199,6 +202,14 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
{installedApps && !installedApps?.find((app) => app.slug == OFFICE_365_VIDEO) && (
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem color="secondary" onClick={() => setIsAccountModalOpen(true)}>
|
||||
{t("office_365_video")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</Dropdown>
|
||||
);
|
||||
@@ -257,6 +268,12 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
app={modal.app}
|
||||
handleRemoveApp={handleRemoveApp}
|
||||
/>
|
||||
|
||||
<AccountDialog
|
||||
open={isAccountModalOpen}
|
||||
onOpenChange={setIsAccountModalOpen}
|
||||
handleSubmit={() => connect(OFFICE_365_VIDEO)}
|
||||
/>
|
||||
</>
|
||||
</SettingsHeader>
|
||||
</AtomsWrapper>
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
|
||||
import { SUCCESS_STATUS, ERROR_STATUS, ZOOM, GOOGLE_MEET } from "@calcom/platform-constants";
|
||||
import {
|
||||
SUCCESS_STATUS,
|
||||
ERROR_STATUS,
|
||||
ZOOM,
|
||||
GOOGLE_MEET,
|
||||
OFFICE_365_VIDEO,
|
||||
} from "@calcom/platform-constants";
|
||||
import type { ApiErrorResponse, ApiResponse } from "@calcom/platform-types";
|
||||
import type { App } from "@calcom/types/App";
|
||||
|
||||
@@ -12,7 +18,7 @@ export type UseGetOauthAuthUrlProps = {
|
||||
onErrorReturnTo?: string;
|
||||
};
|
||||
|
||||
export const useGetOauthAuthUrl = ({ returnTo, onErrorReturnTo }: UseGetOauthAuthUrlProps) => {
|
||||
export const useGetZoomOauthAuthUrl = ({ returnTo, onErrorReturnTo }: UseGetOauthAuthUrlProps) => {
|
||||
return useQuery({
|
||||
queryKey: ["get-zoom-auth-url"],
|
||||
staleTime: Infinity,
|
||||
@@ -35,6 +41,29 @@ export const useGetOauthAuthUrl = ({ returnTo, onErrorReturnTo }: UseGetOauthAut
|
||||
});
|
||||
};
|
||||
|
||||
export const useOffice365GetOauthAuthUrl = ({ returnTo, onErrorReturnTo }: UseGetOauthAuthUrlProps) => {
|
||||
return useQuery({
|
||||
queryKey: ["get-office365-auth-url"],
|
||||
staleTime: Infinity,
|
||||
enabled: false,
|
||||
queryFn: () => {
|
||||
return http
|
||||
?.get<ApiResponse<{ url: string }>>(
|
||||
`conferencing/${OFFICE_365_VIDEO}/oauth/auth-url${
|
||||
returnTo ? `?returnTo=${encodeURIComponent(returnTo)}` : ""
|
||||
}${onErrorReturnTo ? `&onErrorReturnTo=${encodeURIComponent(onErrorReturnTo)}` : ""}`
|
||||
)
|
||||
.then(({ data: responseBody }) => {
|
||||
if (responseBody.status === SUCCESS_STATUS) {
|
||||
return responseBody.data.url;
|
||||
}
|
||||
if (responseBody.status === ERROR_STATUS) throw new Error(responseBody.error.message);
|
||||
return "";
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export type UseConnectGoogleMeetProps = {
|
||||
onSuccess?: (res: ApiResponse) => void;
|
||||
onError?: (err: ApiErrorResponse) => void;
|
||||
@@ -69,18 +98,25 @@ export const useConnectNonOauthApp = (
|
||||
};
|
||||
|
||||
export const useConnect = ({ returnTo, onErrorReturnTo, ...props }: UseConnectGoogleMeetProps) => {
|
||||
const { refetch } = useGetOauthAuthUrl({ returnTo, onErrorReturnTo });
|
||||
const { refetch: refetchZoomAuthUrl } = useGetZoomOauthAuthUrl({ returnTo, onErrorReturnTo });
|
||||
const { refetch: refetchOffice365AuthUrl } = useOffice365GetOauthAuthUrl({ returnTo, onErrorReturnTo });
|
||||
const connectNonOauthApp = useConnectNonOauthApp(props);
|
||||
|
||||
const connect = async (app: App["slug"]) => {
|
||||
switch (app) {
|
||||
case ZOOM:
|
||||
const redirectUri = await refetch();
|
||||
if (redirectUri.data) {
|
||||
window.location.href = redirectUri.data;
|
||||
const zoomRedirectUri = await refetchZoomAuthUrl();
|
||||
if (zoomRedirectUri.data) {
|
||||
window.location.href = zoomRedirectUri.data;
|
||||
}
|
||||
break;
|
||||
|
||||
case OFFICE_365_VIDEO:
|
||||
const office365RedirectUri = await refetchOffice365AuthUrl();
|
||||
if (office365RedirectUri.data) {
|
||||
window.location.href = office365RedirectUri.data;
|
||||
}
|
||||
break;
|
||||
case GOOGLE_MEET:
|
||||
connectNonOauthApp.mutate(app);
|
||||
|
||||
|
||||
@@ -20,9 +20,13 @@ export const GOOGLE_MEET_ID = "google-meet";
|
||||
export const ZOOM = "zoom";
|
||||
export const ZOOM_TYPE = "zoom_video";
|
||||
|
||||
export const CAL_VIDEO = "daily-video";
|
||||
export const OFFICE_365_VIDEO = "msteams";
|
||||
export const OFFICE_365_VIDEO_TYPE = "office365_video";
|
||||
|
||||
export const CONFERENCING_APPS = [GOOGLE_MEET, ZOOM];
|
||||
export const CAL_VIDEO = "daily-video";
|
||||
export const CAL_VIDEO_TYPE = "daily_video";
|
||||
|
||||
export const CONFERENCING_APPS = [GOOGLE_MEET, ZOOM, OFFICE_365_VIDEO];
|
||||
export const APPS_TYPE_ID_MAPPING = {
|
||||
[GOOGLE_CALENDAR_TYPE]: GOOGLE_CALENDAR_ID,
|
||||
[OFFICE_365_CALENDAR_TYPE]: OFFICE_365_CALENDAR_ID,
|
||||
|
||||
Reference in New Issue
Block a user