import { AppSettings } from "@calcom/app-store/_components/AppSettings"; import type { ConnectedApps } from "@calcom/app-store/_utils/getConnectedApps"; import { InstallAppButton } from "@calcom/app-store/InstallAppButton"; import { type EventLocationType, getLocationFromApp } from "@calcom/app-store/locations"; import type { AppCardApp } from "@calcom/app-store/types"; import type { UpdateUsersDefaultConferencingAppParams } from "@calcom/features/apps/components/AppSetDefaultLinkDialog"; import { AppSetDefaultLinkDialog } from "@calcom/features/apps/components/AppSetDefaultLinkDialog"; import type { BulkUpdatParams, EventTypes, } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal"; import { BulkEditDefaultForEventsModal } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal"; import { isDelegationCredential } from "@calcom/lib/delegationCredential"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { AppCategories } from "@calcom/prisma/enums"; import type { DefaultConferencingApp } from "@calcom/prisma/zod-utils"; import type { App } from "@calcom/types/App"; import { Alert } from "@calcom/ui/components/alert"; import type { AppListCardProps } from "@calcom/ui/components/app-list-card"; import { Button } from "@calcom/ui/components/button"; import { Dropdown, DropdownItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@calcom/ui/components/dropdown"; import { List } from "@calcom/ui/components/list"; import { showToast } from "@calcom/ui/components/toast"; import type { ComponentType, ReactNode } from "react"; import { useCallback, useState } from "react"; export type HandleDisconnect = (credentialId: number, app: App["slug"], teamId?: number) => void; interface AppListProps { variant?: AppCategories; data: ConnectedApps; handleDisconnect: HandleDisconnect; listClassName?: string; appCardClassName?: string; appCardMenuClassName?: string; defaultConferencingApp: DefaultConferencingApp | undefined; handleUpdateUserDefaultConferencingApp: (params: UpdateUsersDefaultConferencingAppParams) => void; handleBulkUpdateDefaultLocation: (params: BulkUpdatParams) => void; isBulkUpdateDefaultLocationPending: boolean; eventTypes?: EventTypes; isEventTypesFetching?: boolean; handleConnectDisconnectIntegrationMenuToggle: () => void; handleBulkEditDialogToggle: () => void; AppListCardComponent: ComponentType; } export const AppList = ({ data, handleDisconnect, variant, listClassName, appCardClassName, appCardMenuClassName, defaultConferencingApp, handleUpdateUserDefaultConferencingApp, handleBulkUpdateDefaultLocation, isBulkUpdateDefaultLocationPending, eventTypes, isEventTypesFetching, handleConnectDisconnectIntegrationMenuToggle, handleBulkEditDialogToggle, AppListCardComponent, }: AppListProps) => { const [bulkUpdateModal, setBulkUpdateModal] = useState(false); const [locationType, setLocationType] = useState<(EventLocationType & { slug: string }) | undefined>( undefined ); const onSuccessCallback = useCallback(() => { setBulkUpdateModal(true); showToast("Default app updated successfully", "success"); }, []); const ChildAppCard = ({ item }: { item: AppCardApp }) => { const appSlug = item?.slug; const appIsDefault = appSlug === defaultConferencingApp?.appSlug || (appSlug === "daily-video" && !defaultConferencingApp?.appSlug); return ( 0 : false} credentialOwner={item?.credentialOwner} className={appCardClassName} actions={ !item.credentialOwner?.readOnly ? (
) : null }>
); }; const appsWithTeamCredentials = data.items.filter((app) => app.teams.length); const cardsForAppsWithTeams = appsWithTeamCredentials.map((app) => { const appCards = []; if (app.userCredentialIds.length) { appCards.push(); } for (const team of app.teams) { if (team) { appCards.push( ); } } return appCards; }); const { t } = useLocale(); return ( <> {cardsForAppsWithTeams.map((apps) => apps.map((cards) => cards))} {data.items .filter((item) => item.invalidCredentialIds) .map((item, i) => { if (!item.teams.length) return ; })} {locationType && ( setLocationType(undefined)} onSuccess={onSuccessCallback} handleUpdateUserDefaultConferencingApp={handleUpdateUserDefaultConferencingApp} /> )} {bulkUpdateModal && ( )} ); }; function ConnectOrDisconnectIntegrationMenuItem(props: { credentialId: number; type: App["type"]; isGlobal?: boolean; installed?: boolean; invalidCredentialIds?: number[]; teamId?: number; app: App["slug"]; handleDisconnect: HandleDisconnect; handleConnectDisconnectIntegrationMenuToggle: () => void; }) { const { type, credentialId, isGlobal, installed, handleDisconnect, teamId, app } = props; const { t } = useLocale(); if (credentialId || type === "stripe_payment" || isGlobal) { return ( handleDisconnect(credentialId, app, teamId)} disabled={isGlobal || isDelegationCredential({ credentialId })} StartIcon="trash"> {t("remove_app")} ); } if (!installed) { return (
); } return ( ( )} onChanged={props.handleConnectDisconnectIntegrationMenuToggle} /> ); }