fix: disable google-meet in user onboarding if google-calendar is not installed (#15702)

* fix: disable google-meet in user onboarding if google-calendar is not installed

* add tooltip

* fix: type check

* fix: type check for tooltip

- allowed `ReactNode` for tooltip content prop

---------

Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
This commit is contained in:
Somay Chauhan
2024-07-10 10:34:14 +00:00
committed by GitHub
co-authored by Hariom Balhara
parent ad61d48706
commit fed3987028
5 changed files with 66 additions and 7 deletions
@@ -1,6 +1,11 @@
import Link from "next/link";
import type { TDependencyData } from "@calcom/app-store/_appRegistry";
import { InstallAppButtonWithoutPlanCheck } from "@calcom/app-store/components";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { App } from "@calcom/types/App";
import { Icon } from "@calcom/ui";
import { Button } from "@calcom/ui";
interface IAppConnectionItem {
@@ -9,11 +14,13 @@ interface IAppConnectionItem {
logo: string;
type: App["type"];
installed?: boolean;
dependencyData?: TDependencyData;
}
const AppConnectionItem = (props: IAppConnectionItem) => {
const { title, logo, type, installed } = props;
const { t } = useLocale();
const dependency = props.dependencyData?.find((data) => !data.installed);
return (
<div className="flex flex-row items-center justify-between p-5">
<div className="flex items-center space-x-3">
@@ -26,9 +33,43 @@ const AppConnectionItem = (props: IAppConnectionItem) => {
<Button
{...buttonProps}
color="secondary"
disabled={installed}
disabled={installed || !!dependency}
type="button"
loading={buttonProps?.isPending}
tooltip={
dependency ? (
<div className="items-start space-x-2.5">
<div className="flex items-start">
<div>
<Icon name="circle-alert" className="mr-2 mt-1 font-semibold" />
</div>
<div>
<span className="text-xs font-semibold">
{t("this_app_requires_connected_account", {
appName: title,
dependencyName: dependency.name,
})}
</span>
<div>
<div>
<>
<Link
href={`${WEBAPP_URL}/getting-started/connected-calendar`}
className="flex items-center text-xs underline">
<span className="mr-1">
{t("connect_app", { dependencyName: dependency.name })}
</span>
<Icon name="arrow-right" className="inline-block h-3 w-3" />
</Link>
</>
</div>
</div>
</div>
</div>
</div>
) : undefined
}
onClick={(event) => {
// Save cookie key to return url step
document.cookie = `return-to=${window.location.href};path=/;max-age=3600;SameSite=Lax`;
@@ -37,6 +37,7 @@ const ConnectedVideoStep = (props: ConnectedAppStepProps) => {
type={item.type}
title={item.name}
description={item.description}
dependencyData={item.dependencyData}
logo={item.logo}
installed={item.userCredentialIds.length > 0}
/>
+6 -4
View File
@@ -7,6 +7,11 @@ import { userMetadata } from "@calcom/prisma/zod-utils";
import type { AppFrontendPayload as App } from "@calcom/types/App";
import type { CredentialFrontendPayload as Credential } from "@calcom/types/Credential";
export type TDependencyData = {
name?: string;
installed?: boolean;
}[];
/**
* Get App metdata either using dirName or slug
*/
@@ -96,10 +101,7 @@ export async function getAppRegistryWithCredentials(userId: number, userAdminTea
/* This is now handled from the DB */
// if (!app.installed) return apps;
app.createdAt = dbapp.createdAt.toISOString();
let dependencyData: {
name?: string;
installed?: boolean;
}[] = [];
let dependencyData: TDependencyData = [];
if (app.dependencies) {
dependencyData = app.dependencies.map((dependency) => {
const dependencyInstalled = dbApps.some(
@@ -1,7 +1,9 @@
import type { Prisma } from "@prisma/client";
import appStore from "@calcom/app-store";
import type { TDependencyData } from "@calcom/app-store/_appRegistry";
import type { CredentialOwner } from "@calcom/app-store/types";
import { getAppFromSlug } from "@calcom/app-store/utils";
import getEnabledAppsFromCredentials from "@calcom/lib/apps/getEnabledAppsFromCredentials";
import getInstallCountPerApp from "@calcom/lib/apps/getInstallCountPerApp";
import { getUsersCredentials } from "@calcom/lib/server/getUsersCredentials";
@@ -179,6 +181,18 @@ export const integrationsHandler = async ({ ctx, input }: IntegrationsOptions) =
}
}
let dependencyData: TDependencyData = [];
if (app.dependencies?.length) {
dependencyData = app.dependencies.map((dependency) => {
const dependencyInstalled = enabledApps.some(
(dbAppIterator) => dbAppIterator.credentials.length && dbAppIterator.slug === dependency
);
// If the app marked as dependency is simply deleted from the codebase, we can have the situation where App is marked installed in DB but we couldn't get the app.
const dependencyName = getAppFromSlug(dependency)?.name;
return { name: dependencyName, installed: dependencyInstalled };
});
}
return {
...app,
...(teams.length && {
@@ -189,6 +203,7 @@ export const integrationsHandler = async ({ ctx, input }: IntegrationsOptions) =
teams,
isInstalled: !!userCredentialIds.length || !!teams.length || app.isGlobal,
isSetupAlready,
...(app.dependencies && { dependencyData }),
};
})
);
+2 -2
View File
@@ -22,7 +22,7 @@ export type ButtonBaseProps = {
EndIcon?: IconName;
shallow?: boolean;
/**Tool tip used when icon size is set to small */
tooltip?: string;
tooltip?: string | React.ReactNode;
tooltipSide?: "top" | "right" | "bottom" | "left";
tooltipOffset?: number;
disabled?: boolean;
@@ -240,7 +240,7 @@ const Wrapper = ({
tooltipSide,
tooltipOffset,
}: {
tooltip?: string;
tooltip?: string | React.ReactNode;
children: React.ReactNode;
tooltipSide?: "top" | "right" | "bottom" | "left";
tooltipOffset?: number;