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:
co-authored by
Hariom Balhara
parent
ad61d48706
commit
fed3987028
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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 }),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user