From e5fd455a30d78ea9a48037bc1373028a17ad6004 Mon Sep 17 00:00:00 2001 From: Rajiv Sahal Date: Thu, 12 Mar 2026 15:30:20 +0530 Subject: [PATCH] refactor: move `AppList` to features with slot props (#28100) * refactor: move AppSetDefaultLinkDialog to features + inline QueryCell + fix broken type import Co-Authored-By: rajiv@cal.com * refactor: move AppList to features with slot props + delete AppListCard switcher Co-Authored-By: rajiv@cal.com * fix: correct ConnectedApps type to avoid double nesting of items Co-Authored-By: rajiv@cal.com --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../components/apps/CalendarListContainer.tsx | 5 +- .../modules/apps/components/AdminAppsList.tsx | 29 +++-- .../modules/apps/components/AppListCard.tsx | 25 ---- .../ConferencingAppsViewWebWrapper.tsx | 14 +-- .../[category]/installed-category-view.tsx | 19 ++- .../SelectedCalendarsSettingsWebWrapper.tsx | 8 +- .../features}/apps/components/AppList.tsx | 27 +++-- .../components/AppSetDefaultLinkDialog.tsx | 0 .../AppListCardPlatformWrapper.tsx | 2 +- .../ConferencingAppsViewPlatformWrapper.tsx | 108 +++++++++--------- 10 files changed, 104 insertions(+), 133 deletions(-) delete mode 100644 apps/web/modules/apps/components/AppListCard.tsx rename {apps/web/modules => packages/features}/apps/components/AppList.tsx (92%) rename {apps/web/modules => packages/features}/apps/components/AppSetDefaultLinkDialog.tsx (100%) rename {apps/web/modules/apps/components => packages/platform/atoms/connect/conferencing-apps}/AppListCardPlatformWrapper.tsx (100%) diff --git a/apps/web/components/apps/CalendarListContainer.tsx b/apps/web/components/apps/CalendarListContainer.tsx index a1c6b3d662..ed38cdb0f8 100644 --- a/apps/web/components/apps/CalendarListContainer.tsx +++ b/apps/web/components/apps/CalendarListContainer.tsx @@ -11,12 +11,11 @@ import { ShellSubHeading } from "@calcom/ui/components/layout"; import { List } from "@calcom/ui/components/list"; import { showToast } from "@calcom/ui/components/toast"; import { revalidateSettingsCalendars } from "@calcom/web/app/cache/path/settings/my-account"; -import AppListCard from "@calcom/web/modules/apps/components/AppListCard"; +import AppListCardWebWrapper from "@calcom/web/modules/apps/components/AppListCardWebWrapper"; import { SkeletonLoader } from "@calcom/web/modules/apps/components/SkeletonLoader"; import { SelectedCalendarsSettingsWebWrapper } from "@calcom/web/modules/calendars/components/SelectedCalendarsSettingsWebWrapper"; import SubHeadingTitleWithConnections from "@components/integrations/SubHeadingTitleWithConnections"; import useRouterQuery from "@lib/hooks/useRouterQuery"; - import { QueryCell } from "@lib/QueryCell"; import { Suspense, useEffect } from "react"; import { DestinationCalendarSettingsWebWrapper } from "./DestinationCalendarSettingsWebWrapper"; @@ -45,7 +44,7 @@ function CalendarList(props: Props): JSX.Element { success={({ data }) => ( {data.items.map((item) => ( - - - dynamic( - () => (isPlatform ? import("./AppListCardPlatformWrapper") : import("./AppListCardWebWrapper")), - { - ssr: false, // Prevents SSR issues if needed - } - ), - [isPlatform] - ); - - return ; -} diff --git a/apps/web/modules/apps/components/ConferencingAppsViewWebWrapper.tsx b/apps/web/modules/apps/components/ConferencingAppsViewWebWrapper.tsx index 9cf76140ee..a8e1ee296c 100644 --- a/apps/web/modules/apps/components/ConferencingAppsViewWebWrapper.tsx +++ b/apps/web/modules/apps/components/ConferencingAppsViewWebWrapper.tsx @@ -1,18 +1,17 @@ "use client"; -import { useReducer } from "react"; - +import { AppList } from "@calcom/features/apps/components/AppList"; +import DisconnectIntegrationModal from "@calcom/features/apps/components/DisconnectIntegrationModal"; import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { trpc } from "@calcom/trpc/react"; import type { RouterOutputs } from "@calcom/trpc/react"; +import { trpc } from "@calcom/trpc/react"; import { Button } from "@calcom/ui/components/button"; import { EmptyScreen } from "@calcom/ui/components/empty-screen"; -import { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton"; +import { SkeletonContainer, SkeletonText } from "@calcom/ui/components/skeleton"; import { showToast } from "@calcom/ui/components/toast"; - -import { AppList } from "./AppList"; -import DisconnectIntegrationModal from "@calcom/features/apps/components/DisconnectIntegrationModal"; +import AppListCardWebWrapper from "@calcom/web/modules/apps/components/AppListCardWebWrapper"; +import { useReducer } from "react"; export type UpdateUsersDefaultConferencingAppParams = { appSlug: string; @@ -142,6 +141,7 @@ export const InstalledConferencingApps = ({ isEventTypesFetching={false} handleConnectDisconnectIntegrationMenuToggle={handleConnectDisconnectIntegrationMenuToggle} handleBulkEditDialogToggle={handleBulkEditDialogToggle} + AppListCardComponent={AppListCardWebWrapper} /> ); }; diff --git a/apps/web/modules/apps/installed/[category]/installed-category-view.tsx b/apps/web/modules/apps/installed/[category]/installed-category-view.tsx index 985509d547..495cda2781 100644 --- a/apps/web/modules/apps/installed/[category]/installed-category-view.tsx +++ b/apps/web/modules/apps/installed/[category]/installed-category-view.tsx @@ -1,28 +1,26 @@ "use client"; -import { useReducer } from "react"; - import getAppCategoryTitle from "@calcom/app-store/_utils/getAppCategoryTitle"; -import { AppList, type HandleDisconnect } from "@calcom/web/modules/apps/components/AppList"; -import type { UpdateUsersDefaultConferencingAppParams } from "@calcom/web/modules/apps/components/AppSetDefaultLinkDialog"; -import DisconnectIntegrationModal from "@calcom/features/apps/components/DisconnectIntegrationModal"; +import { AppList, type HandleDisconnect } from "@calcom/features/apps/components/AppList"; +import type { UpdateUsersDefaultConferencingAppParams } from "@calcom/features/apps/components/AppSetDefaultLinkDialog"; import type { RemoveAppParams } from "@calcom/features/apps/components/DisconnectIntegrationModal"; -import { SkeletonLoader } from "@calcom/web/modules/apps/components/SkeletonLoader"; +import DisconnectIntegrationModal from "@calcom/features/apps/components/DisconnectIntegrationModal"; import type { BulkUpdatParams } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { AppCategories } from "@calcom/prisma/enums"; -import { trpc } from "@calcom/trpc/react"; import type { RouterOutputs } from "@calcom/trpc/react"; +import { trpc } from "@calcom/trpc/react"; import { Button } from "@calcom/ui/components/button"; import { EmptyScreen } from "@calcom/ui/components/empty-screen"; import type { Icon } from "@calcom/ui/components/icon"; import { ShellSubHeading } from "@calcom/ui/components/layout"; import { showToast } from "@calcom/ui/components/toast"; - -import { QueryCell } from "@lib/QueryCell"; - +import AppListCardWebWrapper from "@calcom/web/modules/apps/components/AppListCardWebWrapper"; +import { SkeletonLoader } from "@calcom/web/modules/apps/components/SkeletonLoader"; import { CalendarListContainer } from "@components/apps/CalendarListContainer"; import InstalledAppsLayout from "@components/apps/layouts/InstalledAppsLayout"; +import { QueryCell } from "@lib/QueryCell"; +import { useReducer } from "react"; interface IntegrationsContainerProps { variant?: AppCategories; @@ -166,6 +164,7 @@ const IntegrationsContainer = ({ isEventTypesFetching={isEventTypesFetching} handleConnectDisconnectIntegrationMenuToggle={handleConnectDisconnectIntegrationMenuToggle} handleBulkEditDialogToggle={handleBulkEditDialogToggle} + AppListCardComponent={AppListCardWebWrapper} /> ); diff --git a/apps/web/modules/calendars/components/SelectedCalendarsSettingsWebWrapper.tsx b/apps/web/modules/calendars/components/SelectedCalendarsSettingsWebWrapper.tsx index 86a9eb2765..50c6b142ad 100644 --- a/apps/web/modules/calendars/components/SelectedCalendarsSettingsWebWrapper.tsx +++ b/apps/web/modules/calendars/components/SelectedCalendarsSettingsWebWrapper.tsx @@ -5,10 +5,10 @@ import { trpc } from "@calcom/trpc/react"; import { Alert } from "@calcom/ui/components/alert"; import { Select } from "@calcom/ui/components/form"; import { List } from "@calcom/ui/components/list"; -import AppListCard from "@calcom/web/modules/apps/components/AppListCard"; +import AppListCardWebWrapper from "@calcom/web/modules/apps/components/AppListCardWebWrapper"; import CredentialActionsDropdown from "@calcom/web/modules/apps/components/CredentialActionsDropdown"; -import { CalendarSwitch } from "@calcom/web/modules/calendars/components/CalendarSwitch"; import AdditionalCalendarSelector from "@calcom/web/modules/calendars/components/AdditionalCalendarSelector"; +import { CalendarSwitch } from "@calcom/web/modules/calendars/components/CalendarSwitch"; import Link from "next/link"; import React from "react"; @@ -57,7 +57,7 @@ const ConnectedCalendarList = ({ {items.map((connectedCalendar) => { if (!!connectedCalendar.calendars && connectedCalendar.calendars.length > 0) { return ( - )} - + ); } return ( diff --git a/apps/web/modules/apps/components/AppList.tsx b/packages/features/apps/components/AppList.tsx similarity index 92% rename from apps/web/modules/apps/components/AppList.tsx rename to packages/features/apps/components/AppList.tsx index 0b60bb3ee7..3608437d9d 100644 --- a/apps/web/modules/apps/components/AppList.tsx +++ b/packages/features/apps/components/AppList.tsx @@ -1,12 +1,10 @@ -import { useCallback, useState } from "react"; - -import { InstallAppButton } from "@calcom/app-store/InstallAppButton"; import { AppSettings } from "@calcom/app-store/_components/AppSettings"; -import { getLocationFromApp, type EventLocationType } from "@calcom/app-store/locations"; +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 AppListCard from "@calcom/web/modules/apps/components/AppListCard"; -import type { UpdateUsersDefaultConferencingAppParams } from "@calcom/web/modules/apps/components/AppSetDefaultLinkDialog"; -import { AppSetDefaultLinkDialog } from "@calcom/web/modules/apps/components/AppSetDefaultLinkDialog"; +import type { UpdateUsersDefaultConferencingAppParams } from "@calcom/features/apps/components/AppSetDefaultLinkDialog"; +import { AppSetDefaultLinkDialog } from "@calcom/features/apps/components/AppSetDefaultLinkDialog"; import type { BulkUpdatParams, EventTypes, @@ -15,9 +13,10 @@ import { BulkEditDefaultForEventsModal } from "@calcom/features/eventtypes/compo import { isDelegationCredential } from "@calcom/lib/delegationCredential"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { AppCategories } from "@calcom/prisma/enums"; -import { type RouterOutputs } from "@calcom/trpc/react"; +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, @@ -28,17 +27,19 @@ import { } 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: RouterOutputs["viewer"]["apps"]["integrations"]; + data: ConnectedApps; handleDisconnect: HandleDisconnect; listClassName?: string; appCardClassName?: string; appCardMenuClassName?: string; - defaultConferencingApp: RouterOutputs["viewer"]["apps"]["getUsersDefaultConferencingApp"]; + defaultConferencingApp: DefaultConferencingApp | undefined; handleUpdateUserDefaultConferencingApp: (params: UpdateUsersDefaultConferencingAppParams) => void; handleBulkUpdateDefaultLocation: (params: BulkUpdatParams) => void; isBulkUpdateDefaultLocationPending: boolean; @@ -46,6 +47,7 @@ interface AppListProps { isEventTypesFetching?: boolean; handleConnectDisconnectIntegrationMenuToggle: () => void; handleBulkEditDialogToggle: () => void; + AppListCardComponent: ComponentType; } export const AppList = ({ @@ -63,6 +65,7 @@ export const AppList = ({ isEventTypesFetching, handleConnectDisconnectIntegrationMenuToggle, handleBulkEditDialogToggle, + AppListCardComponent, }: AppListProps) => { const [bulkUpdateModal, setBulkUpdateModal] = useState(false); const [locationType, setLocationType] = useState<(EventLocationType & { slug: string }) | undefined>( @@ -79,7 +82,7 @@ export const AppList = ({ appSlug === defaultConferencingApp?.appSlug || (appSlug === "daily-video" && !defaultConferencingApp?.appSlug); return ( - - + ); }; diff --git a/apps/web/modules/apps/components/AppSetDefaultLinkDialog.tsx b/packages/features/apps/components/AppSetDefaultLinkDialog.tsx similarity index 100% rename from apps/web/modules/apps/components/AppSetDefaultLinkDialog.tsx rename to packages/features/apps/components/AppSetDefaultLinkDialog.tsx diff --git a/apps/web/modules/apps/components/AppListCardPlatformWrapper.tsx b/packages/platform/atoms/connect/conferencing-apps/AppListCardPlatformWrapper.tsx similarity index 100% rename from apps/web/modules/apps/components/AppListCardPlatformWrapper.tsx rename to packages/platform/atoms/connect/conferencing-apps/AppListCardPlatformWrapper.tsx index 531e64fae4..b5c4e25f49 100644 --- a/apps/web/modules/apps/components/AppListCardPlatformWrapper.tsx +++ b/packages/platform/atoms/connect/conferencing-apps/AppListCardPlatformWrapper.tsx @@ -1,5 +1,5 @@ -import { AppListCard } from "@calcom/ui/components/app-list-card"; import type { AppListCardProps } from "@calcom/ui/components/app-list-card"; +import { AppListCard } from "@calcom/ui/components/app-list-card"; export default function AppListCardPlatformWrapper(props: AppListCardProps) { const logo = `https://app.cal.com${props.logo}`; diff --git a/packages/platform/atoms/connect/conferencing-apps/ConferencingAppsViewPlatformWrapper.tsx b/packages/platform/atoms/connect/conferencing-apps/ConferencingAppsViewPlatformWrapper.tsx index 49c45d82a5..e8524ea0c9 100644 --- a/packages/platform/atoms/connect/conferencing-apps/ConferencingAppsViewPlatformWrapper.tsx +++ b/packages/platform/atoms/connect/conferencing-apps/ConferencingAppsViewPlatformWrapper.tsx @@ -1,11 +1,13 @@ "use client"; import AccountDialog from "@calcom/app-store/office365video/components/AccountDialog"; +import { AppList } from "@calcom/features/apps/components/AppList"; +import type { UpdateUsersDefaultConferencingAppParams } from "@calcom/features/apps/components/AppSetDefaultLinkDialog"; import DisconnectIntegrationModal from "@calcom/features/apps/components/DisconnectIntegrationModal"; +import type { BulkUpdatParams } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal"; import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { GOOGLE_MEET, OFFICE_365_VIDEO, ZOOM } from "@calcom/platform-constants"; -import { QueryCell } from "@calcom/trpc/components/QueryCell"; import type { App } from "@calcom/types/App"; import { Button } from "@calcom/ui/components/button"; import { @@ -17,16 +19,12 @@ import { } from "@calcom/ui/components/dropdown"; import { EmptyScreen } from "@calcom/ui/components/empty-screen"; import { SkeletonContainer, SkeletonText } from "@calcom/ui/components/skeleton"; -import { AppList } from "@calcom/web/modules/apps/components/AppList"; import { useQueryClient } from "@tanstack/react-query"; import { useReducer, useState } from "react"; import { AtomsWrapper } from "../../src/components/atoms-wrapper"; import { useToast } from "../../src/components/ui/use-toast"; import { cn } from "../../src/lib/utils"; -import type { - BulkUpdatParams, - UpdateUsersDefaultConferencingAppParams, -} from "./ConferencingAppsViewWebWrapper"; +import AppListCardPlatformWrapper from "./AppListCardPlatformWrapper"; import { useAtomBulkUpdateEventTypesToDefaultLocation } from "./hooks/useAtomBulkUpdateEventTypesToDefaultLocation"; import { useAtomGetEventTypes } from "./hooks/useAtomGetEventTypes"; import { @@ -286,56 +284,56 @@ export const ConferencingAppsViewPlatformWrapper = ({ borderInShellHeader={true}> <>
- } - success={({ data }) => { - if (!data.items.length) { - return ( - - } - className={customClassNames?.emptyScreenClassName} - iconWrapperClassName={customClassNames?.emptyScreenIconWrapperClassName} - iconClassName={customClassNames?.emptyScreenIconClassName} - /> - ); - } - return ( - + ) : installedIntegrationsQuery.status === "error" ? ( + + ) : !installedIntegrationsQuery.data.items.length ? ( + - ); - }} - /> + } + className={customClassNames?.emptyScreenClassName} + iconWrapperClassName={customClassNames?.emptyScreenIconWrapperClassName} + iconClassName={customClassNames?.emptyScreenIconClassName} + /> + ) : ( + + )}