From b6de03de96af5a5197375a06c3552c0846d56e0d Mon Sep 17 00:00:00 2001 From: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Date: Fri, 30 May 2025 01:40:12 +0530 Subject: [PATCH] Revert "perf: use app dir to fetch team feature flags in settings (#21433)" (#21628) This reverts commit 1dca160db08ad102a44ceea81155ac2475093ce6. --- .../SettingsLayoutAppDirClient.tsx | 35 ++++++------------- .../settings/(settings-layout)/layout.tsx | 17 +-------- .../features/flags/features.repository.ts | 22 ------------ .../flags/hooks/useIsFeatureEnabledForTeam.ts | 16 --------- .../viewer/delegationCredential/_router.ts | 8 +++++ 5 files changed, 19 insertions(+), 79 deletions(-) delete mode 100644 packages/features/flags/hooks/useIsFeatureEnabledForTeam.ts diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx index 1275a84464..4901b8b0c2 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx @@ -10,8 +10,6 @@ import React, { useEffect, useState, useMemo } from "react"; import { checkAdminOrOwner } from "@calcom/features/auth/lib/checkAdminOrOwner"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; import type { OrganizationBranding } from "@calcom/features/ee/organizations/context/provider"; -import type { AppFlags } from "@calcom/features/flags/config"; -import { useIsFeatureEnabledForTeam } from "@calcom/features/flags/hooks/useIsFeatureEnabledForTeam"; import Shell from "@calcom/features/shell/Shell"; import { HOSTED_CAL_FEATURES, IS_CALCOM, WEBAPP_URL } from "@calcom/lib/constants"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; @@ -29,8 +27,6 @@ import type { VerticalTabItemProps } from "@calcom/ui/components/navigation"; import { VerticalTabItem } from "@calcom/ui/components/navigation"; import { Skeleton } from "@calcom/ui/components/skeleton"; -type TeamFeatures = Record> | null; - const getTabs = (orgBranding: OrganizationBranding | null) => { const tabs: VerticalTabItemProps[] = [ { @@ -276,7 +272,6 @@ interface SettingsSidebarContainerProps { className?: string; navigationIsOpenedOnMobile?: boolean; bannersHeight?: number; - teamFeatures?: TeamFeatures; } const TeamListCollapsible = () => { @@ -443,7 +438,6 @@ const SettingsSidebarContainer = ({ className = "", navigationIsOpenedOnMobile, bannersHeight, - teamFeatures, }: SettingsSidebarContainerProps) => { const searchParams = useCompatSearchParams(); const orgBranding = useOrgBranding(); @@ -455,15 +449,11 @@ const SettingsSidebarContainer = ({ }[] >(); const session = useSession(); - - const isDelegationCredentialEnabled = useIsFeatureEnabledForTeam({ - teamFeatures, - teamId: session.data?.user?.org?.id, - feature: "delegation-credential", + const { data } = trpc.viewer.delegationCredential.check.useQuery(undefined, { + enabled: !!session.data?.user?.org, }); - const tabsWithPermissions = useTabs({ - isDelegationCredentialEnabled, + isDelegationCredentialEnabled: data?.hasDelegationCredential ?? false, }); const { data: otherTeams } = trpc.viewer.organizations.listOtherTeams.useQuery(undefined, { @@ -737,10 +727,9 @@ const MobileSettingsContainer = (props: { onSideContainerOpen?: () => void }) => export type SettingsLayoutProps = { children: React.ReactNode; containerClassName?: string; - teamFeatures?: TeamFeatures; } & ComponentProps; -export default function SettingsLayoutAppDirClient({ children, teamFeatures, ...rest }: SettingsLayoutProps) { +export default function SettingsLayoutAppDirClient({ children, ...rest }: SettingsLayoutProps) { const pathname = usePathname(); const state = useState(false); const [sideContainerOpen, setSideContainerOpen] = state; @@ -772,7 +761,6 @@ export default function SettingsLayoutAppDirClient({ children, teamFeatures, ... } drawerState={state} @@ -790,18 +778,10 @@ export default function SettingsLayoutAppDirClient({ children, teamFeatures, ... ); } -type SidebarContainerElementProps = { - sideContainerOpen: boolean; - bannersHeight?: number; - setSideContainerOpen: React.Dispatch>; - teamFeatures?: TeamFeatures; -}; - const SidebarContainerElement = ({ sideContainerOpen, bannersHeight, setSideContainerOpen, - teamFeatures, }: SidebarContainerElementProps) => { const { t } = useLocale(); return ( @@ -817,8 +797,13 @@ const SidebarContainerElement = ({ ); }; + +type SidebarContainerElementProps = { + sideContainerOpen: boolean; + bannersHeight?: number; + setSideContainerOpen: React.Dispatch>; +}; diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx index a731c4426b..4e558930ba 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx @@ -3,8 +3,6 @@ import { redirect } from "next/navigation"; import React from "react"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; -import type { AppFlags } from "@calcom/features/flags/config"; -import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { buildLegacyRequest } from "@lib/buildLegacyCtx"; @@ -18,22 +16,9 @@ export default async function SettingsLayoutAppDir(props: SettingsLayoutProps) { return redirect("/auth/login"); } - let teamFeatures: Record> | null = null; - - // For now we only grab organization features but it would be nice to fetch these on the server side for specific team feature flags - if (session?.user.org) { - const featuresRepository = new FeaturesRepository(); - const features = await featuresRepository.getTeamFeatures(session.user.org.id); - if (features) { - teamFeatures = { - [session.user.org.id]: features, - }; - } - } - return ( <> - + ); } diff --git a/packages/features/flags/features.repository.ts b/packages/features/flags/features.repository.ts index e183b51e0f..149c0b6359 100644 --- a/packages/features/flags/features.repository.ts +++ b/packages/features/flags/features.repository.ts @@ -1,7 +1,6 @@ import { Prisma } from "@prisma/client"; import { captureException } from "@sentry/nextjs"; -import kysely from "@calcom/kysely"; import db from "@calcom/prisma"; import type { AppFlags } from "./config"; @@ -59,27 +58,6 @@ export class FeaturesRepository implements IFeaturesRepository { }, {} as AppFlags); } - /** - * Gets all features enabled for a specific team in a map format. - * @param teamId - The ID of the team to get features for - * @returns Promise<{ [slug: string]: boolean } | null> - */ - public async getTeamFeatures(teamId: number) { - const result = await kysely - .selectFrom("TeamFeatures") - .innerJoin("Feature", "Feature.slug", "TeamFeatures.featureId") - .select(["Feature.slug", "Feature.enabled"]) - .where("TeamFeatures.teamId", "=", teamId) - .execute(); - - if (!result.length) return null; - - return result.reduce>((acc, feature) => { - acc[feature.slug as keyof AppFlags] = true; - return acc; - }, {} as Record); - } - /** * Checks if a feature is enabled globally in the application. * @param slug - The feature flag identifier to check diff --git a/packages/features/flags/hooks/useIsFeatureEnabledForTeam.ts b/packages/features/flags/hooks/useIsFeatureEnabledForTeam.ts deleted file mode 100644 index 73809b81ae..0000000000 --- a/packages/features/flags/hooks/useIsFeatureEnabledForTeam.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { AppFlags } from "../config"; - -type TeamFeatures = Record> | null; - -export const useIsFeatureEnabledForTeam = ({ - teamFeatures, - teamId, - feature, -}: { - teamFeatures?: TeamFeatures; - teamId?: number; - feature: keyof AppFlags; -}) => { - if (!teamId || !teamFeatures?.[teamId]) return false; - return teamFeatures[teamId][feature]; -}; diff --git a/packages/trpc/server/routers/viewer/delegationCredential/_router.ts b/packages/trpc/server/routers/viewer/delegationCredential/_router.ts index 0cc8036bf5..5750231d13 100644 --- a/packages/trpc/server/routers/viewer/delegationCredential/_router.ts +++ b/packages/trpc/server/routers/viewer/delegationCredential/_router.ts @@ -45,6 +45,14 @@ const checkDelegationCredentialFeature = async ({ }; export const delegationCredentialRouter = router({ + check: authedOrgAdminProcedure.query(async (opts) => { + return await checkDelegationCredentialFeature({ + ctx: opts.ctx, + next: async () => ({ + hasDelegationCredential: true, + }), + }); + }), list: authedOrgAdminProcedure.use(checkDelegationCredentialFeature).query(async (opts) => { const handler = await import("./list.handler").then((mod) => mod.default); return handler(opts);