2023-03-09 09:07:23 +00:00
import Link from "next/link" ;
2022-07-14 12:40:53 +00:00
import { useRouter } from "next/router" ;
2022-09-15 09:33:34 +00:00
import { useEffect , useRef } from "react" ;
2022-03-23 22:00:30 +00:00
2023-04-18 16:48:19 +00:00
import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation" ;
2023-03-09 09:07:23 +00:00
import classNames from "@calcom/lib/classNames" ;
2022-04-06 12:37:06 +00:00
import { WEBAPP_URL } from "@calcom/lib/constants" ;
2023-03-09 09:07:23 +00:00
import { CAL_URL } from "@calcom/lib/constants" ;
2022-06-07 06:13:32 +00:00
import { deriveAppDictKeyFromType } from "@calcom/lib/deriveAppDictKeyFromType" ;
2023-05-19 09:52:17 +00:00
import { useHasTeamPlan } from "@calcom/lib/hooks/useHasPaidPlan" ;
2023-03-09 09:07:23 +00:00
import { useLocale } from "@calcom/lib/hooks/useLocale" ;
2022-07-22 17:27:06 +00:00
import { trpc } from "@calcom/trpc/react" ;
2023-03-09 09:07:23 +00:00
import type { RouterOutputs } from "@calcom/trpc/react" ;
2022-03-23 22:00:30 +00:00
import type { App } from "@calcom/types/App" ;
2023-04-12 15:26:31 +00:00
import { AlertCircle , ArrowRight , Check } from "@calcom/ui/components/icon" ;
2022-03-23 22:00:30 +00:00
2022-06-07 06:13:32 +00:00
import { InstallAppButtonMap } from "./apps.browser.generated" ;
2022-11-23 02:55:25 +00:00
import type { InstallAppButtonProps } from "./types" ;
2022-03-23 22:00:30 +00:00
2022-09-06 22:58:16 +00:00
export const InstallAppButtonWithoutPlanCheck = (
2022-07-14 12:40:53 +00:00
props : {
type : App [ "type" ] ;
} & InstallAppButtonProps
2022-09-06 22:58:16 +00:00
) = > {
2023-04-18 16:48:19 +00:00
const mutation = useAddAppMutation ( null ) ;
2022-07-14 12:40:53 +00:00
const key = deriveAppDictKeyFromType ( props . type , InstallAppButtonMap ) ;
const InstallAppButtonComponent = InstallAppButtonMap [ key as keyof typeof InstallAppButtonMap ] ;
2023-03-09 09:07:23 +00:00
if ( ! InstallAppButtonComponent )
2023-04-18 16:48:19 +00:00
return (
< >
{ props . render ( {
useDefaultComponent : true ,
disabled : props.disableInstall ,
onClick : ( ) = > {
mutation . mutate ( { type : props . type } ) ;
} ,
} ) }
< / >
) ;
2022-07-14 12:40:53 +00:00
2023-03-09 09:07:23 +00:00
return (
< InstallAppButtonComponent
render = { props . render }
onChanged = { props . onChanged }
disableInstall = { props . disableInstall }
/ >
) ;
2022-09-06 22:58:16 +00:00
} ;
2022-03-23 22:00:30 +00:00
export const InstallAppButton = (
props : {
2023-05-19 09:52:17 +00:00
teamsPlanRequired? : App [ "teamsPlanRequired" ] ;
2022-03-23 22:00:30 +00:00
type : App [ "type" ] ;
2022-09-15 19:53:09 +00:00
wrapperClassName? : string ;
2023-03-09 09:07:23 +00:00
disableInstall? : boolean ;
2022-03-23 22:00:30 +00:00
} & InstallAppButtonProps
) = > {
2023-05-19 09:52:17 +00:00
const { isLoading : isUserLoading , data : user } = trpc . viewer . me . useQuery ( ) ;
2022-07-14 12:40:53 +00:00
const router = useRouter ( ) ;
const proProtectionElementRef = useRef < HTMLDivElement | null > ( null ) ;
2023-05-19 09:52:17 +00:00
const { isLoading : isTeamPlanStatusLoading , hasTeamPlan } = useHasTeamPlan ( ) ;
2022-07-14 12:40:53 +00:00
useEffect ( ( ) = > {
const el = proProtectionElementRef . current ;
if ( ! el ) {
return ;
}
el . addEventListener (
"click" ,
( e ) = > {
if ( ! user ) {
router . push (
` ${ WEBAPP_URL } /auth/login?callbackUrl= ${ WEBAPP_URL + location . pathname + location . search } `
) ;
e . stopPropagation ( ) ;
return ;
}
2023-05-19 09:52:17 +00:00
if ( props . teamsPlanRequired && ! hasTeamPlan ) {
// TODO: I think we should show the UpgradeTip in a Dialog here. This would solve the problem of no way to go back to the App page from the UpgradeTip page(except browser's back button)
router . push ( props . teamsPlanRequired . upgradeUrl ) ;
e . stopPropagation ( ) ;
return ;
}
2022-07-14 12:40:53 +00:00
} ,
true
2022-03-23 22:00:30 +00:00
) ;
2023-05-23 08:44:57 +00:00
} , [ isUserLoading , user , router , hasTeamPlan , props . teamsPlanRequired ] ) ;
2022-07-14 12:40:53 +00:00
2023-05-19 09:52:17 +00:00
if ( isUserLoading || isTeamPlanStatusLoading ) {
2022-07-14 12:40:53 +00:00
return null ;
}
return (
2022-09-15 19:53:09 +00:00
< div ref = { proProtectionElementRef } className = { props . wrapperClassName } >
2022-07-14 12:40:53 +00:00
< InstallAppButtonWithoutPlanCheck { ...props } / >
< / div >
) ;
2022-03-23 22:00:30 +00:00
} ;
2022-05-06 17:21:30 +00:00
export { AppConfiguration } from "./_components/AppConfiguration" ;
2023-03-09 09:07:23 +00:00
export const AppDependencyComponent = ( {
appName ,
dependencyData ,
} : {
appName : string ;
dependencyData : RouterOutputs [ "viewer" ] [ "appsRouter" ] [ "queryForDependencies" ] ;
} ) = > {
const { t } = useLocale ( ) ;
return (
< div
className = { classNames (
"rounded-md py-3 px-4" ,
2023-04-05 18:14:46 +00:00
dependencyData && dependencyData . some ( ( dependency ) = > ! dependency . installed ) ? "bg-info" : "bg-subtle"
2023-03-09 09:07:23 +00:00
) } >
{ dependencyData &&
dependencyData . map ( ( dependency ) = > {
return dependency . installed ? (
< div className = "items-start space-x-2.5" >
< div className = "flex items-start" >
< div >
2023-04-12 15:26:31 +00:00
< Check className = "mt-1 mr-2 font-semibold" / >
2023-03-09 09:07:23 +00:00
< / div >
< div >
< span className = "font-semibold" >
{ t ( "app_is_connected" , { dependencyName : dependency.name } ) }
< / span >
< div >
< div >
< span >
{ t ( "this_app_requires_connected_account" , {
appName ,
dependencyName : dependency.name ,
} ) }
< / span >
< / div >
< / div >
< / div >
< / div >
< / div >
) : (
< div className = "items-start space-x-2.5" >
2023-04-05 18:14:46 +00:00
< div className = "text-info flex items-start" >
2023-03-09 09:07:23 +00:00
< div >
2023-04-12 15:26:31 +00:00
< AlertCircle className = "mt-1 mr-2 font-semibold" / >
2023-03-09 09:07:23 +00:00
< / div >
< div >
< span className = "font-semibold" >
{ t ( "this_app_requires_connected_account" , { appName , dependencyName : dependency.name } ) }
< / span >
< div >
< div >
< >
< Link
href = { ` ${ CAL_URL } /apps/ ${ dependency . slug } ` }
2023-04-05 18:14:46 +00:00
className = "text-info flex items-center underline" >
2023-03-09 09:07:23 +00:00
< span className = "mr-1" >
{ t ( "connect_app" , { dependencyName : dependency.name } ) }
< / span >
2023-04-12 15:26:31 +00:00
< ArrowRight / >
2023-03-09 09:07:23 +00:00
< / Link >
< / >
< / div >
< / div >
< / div >
< / div >
< / div >
) ;
} ) }
< / div >
) ;
} ;