From cacd1b489ea43ea6819469bf840d175ebd05f067 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Wed, 3 Dec 2025 00:03:56 +0530 Subject: [PATCH] [WEB-5559] improvement: chat support functionality and remove Intercom provider (#8217) * [WEB-5559] improve: chat support functionality and remove Intercom provider - Added ChatSupportModal component for chat support integration. - Replaced IntercomProvider with ChatSupportModal in AppProvider. - Introduced useChatSupport hook to manage chat support state and actions. - Updated help commands to utilize chat support instead of Intercom. - Removed obsolete Intercom-related components and hooks. * refactor: lazy load ChatSupportModal in AppProvider --- apps/web/app/provider.tsx | 13 +- .../components/global/chat-support-modal.tsx | 43 +++++ .../power-k/config/help-commands.ts | 10 +- .../workspace/sidebar/help-menu.tsx | 125 --------------- .../workspace/sidebar/help-section.tsx | 147 ------------------ .../workspace/sidebar/help-section/root.tsx | 16 +- apps/web/core/custom-events/chat-support.ts | 13 ++ apps/web/core/hooks/store/use-transient.ts | 11 -- apps/web/core/hooks/use-chat-support.ts | 25 +++ apps/web/core/lib/intercom-provider.tsx | 55 ------- apps/web/core/store/root.store.ts | 5 - apps/web/core/store/transient.store.ts | 28 ---- 12 files changed, 97 insertions(+), 394 deletions(-) create mode 100644 apps/web/core/components/global/chat-support-modal.tsx delete mode 100644 apps/web/core/components/workspace/sidebar/help-menu.tsx delete mode 100644 apps/web/core/components/workspace/sidebar/help-section.tsx create mode 100644 apps/web/core/custom-events/chat-support.ts delete mode 100644 apps/web/core/hooks/store/use-transient.ts create mode 100644 apps/web/core/hooks/use-chat-support.ts delete mode 100644 apps/web/core/lib/intercom-provider.tsx delete mode 100644 apps/web/core/store/transient.store.ts diff --git a/apps/web/app/provider.tsx b/apps/web/app/provider.tsx index 233b4250d..7d6811052 100644 --- a/apps/web/app/provider.tsx +++ b/apps/web/app/provider.tsx @@ -25,8 +25,8 @@ const PostHogProvider = lazy(function PostHogProvider() { return import("@/lib/posthog-provider"); }); -const IntercomProvider = lazy(function IntercomProvider() { - return import("@/lib/intercom-provider"); +const ChatSupportModal = lazy(function ChatSupportModal() { + return import("@/components/global/chat-support-modal"); }); export interface IAppProvider { @@ -50,11 +50,10 @@ export function AppProvider(props: IAppProvider) { - - - {children} - - + + + {children} + diff --git a/apps/web/core/components/global/chat-support-modal.tsx b/apps/web/core/components/global/chat-support-modal.tsx new file mode 100644 index 000000000..75c6c10ad --- /dev/null +++ b/apps/web/core/components/global/chat-support-modal.tsx @@ -0,0 +1,43 @@ +import { useEffect } from "react"; +import { Intercom, shutdown, show } from "@intercom/messenger-js-sdk"; +import { observer } from "mobx-react"; +// custom events +import { CHAT_SUPPORT_EVENTS } from "@/custom-events/chat-support"; +// store hooks +import { useInstance } from "@/hooks/store/use-instance"; +import { useUser } from "@/hooks/store/user"; + +const ChatSupportModal = observer(function ChatSupportModal() { + // store hooks + const { data: user } = useUser(); + const { config } = useInstance(); + // derived values + const intercomAppId = config?.intercom_app_id; + const isEnabled = Boolean(user && config?.is_intercom_enabled && intercomAppId); + + useEffect(() => { + if (!isEnabled || !user || !intercomAppId) return; + + Intercom({ + app_id: intercomAppId, + user_id: user.id, + name: `${user.first_name} ${user.last_name}`, + email: user.email, + hide_default_launcher: true, + }); + + const handleOpenChatSupport = () => { + show(); + }; + + window.addEventListener(CHAT_SUPPORT_EVENTS.open, handleOpenChatSupport); + return () => { + window.removeEventListener(CHAT_SUPPORT_EVENTS.open, handleOpenChatSupport); + shutdown(); + }; + }, [user, intercomAppId, isEnabled]); + + return null; +}); + +export default ChatSupportModal; diff --git a/apps/web/core/components/power-k/config/help-commands.ts b/apps/web/core/components/power-k/config/help-commands.ts index 1f54e6083..9f61a5ceb 100644 --- a/apps/web/core/components/power-k/config/help-commands.ts +++ b/apps/web/core/components/power-k/config/help-commands.ts @@ -5,7 +5,7 @@ import { DiscordIcon } from "@plane/propel/icons"; import type { TPowerKCommandConfig } from "@/components/power-k/core/types"; // hooks import { usePowerK } from "@/hooks/store/use-power-k"; -import { useTransient } from "@/hooks/store/use-transient"; +import { useChatSupport } from "@/hooks/use-chat-support"; /** * Help commands - Help related commands @@ -13,7 +13,7 @@ import { useTransient } from "@/hooks/store/use-transient"; export const usePowerKHelpCommands = (): TPowerKCommandConfig[] => { // store const { toggleShortcutsListModal } = usePowerK(); - const { toggleIntercom } = useTransient(); + const { isEnabled: isChatSupportEnabled, openChatSupport } = useChatSupport(); return [ { @@ -73,9 +73,9 @@ export const usePowerKHelpCommands = (): TPowerKCommandConfig[] => { group: "help", i18n_title: "power_k.help_actions.chat_with_us", icon: MessageSquare, - action: () => toggleIntercom(true), - isEnabled: () => true, - isVisible: () => true, + action: () => openChatSupport(), + isEnabled: () => isChatSupportEnabled, + isVisible: () => isChatSupportEnabled, closeOnSelect: true, }, ]; diff --git a/apps/web/core/components/workspace/sidebar/help-menu.tsx b/apps/web/core/components/workspace/sidebar/help-menu.tsx deleted file mode 100644 index dde2662d1..000000000 --- a/apps/web/core/components/workspace/sidebar/help-menu.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import React, { useState } from "react"; -import { observer } from "mobx-react"; -import { HelpCircle, MessagesSquare, User } from "lucide-react"; -import { useTranslation } from "@plane/i18n"; -import { PageIcon } from "@plane/propel/icons"; -// ui -import { Tooltip } from "@plane/propel/tooltip"; -import { CustomMenu } from "@plane/ui"; -// components -import { cn } from "@plane/utils"; -import { ProductUpdatesModal } from "@/components/global"; -// helpers -// hooks -import { useInstance } from "@/hooks/store/use-instance"; -import { usePowerK } from "@/hooks/store/use-power-k"; -import { useTransient } from "@/hooks/store/use-transient"; -import { usePlatformOS } from "@/hooks/use-platform-os"; -// plane web components -import { PlaneVersionNumber } from "@/plane-web/components/global"; - -export interface WorkspaceHelpSectionProps { - setSidebarActive?: React.Dispatch>; -} - -export const HelpMenu = observer(function HelpMenu(_props: WorkspaceHelpSectionProps) { - // store hooks - const { t } = useTranslation(); - const { toggleShortcutsListModal } = usePowerK(); - const { isMobile } = usePlatformOS(); - const { config } = useInstance(); - const { isIntercomToggle, toggleIntercom } = useTransient(); - // states - const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); - const [isProductUpdatesModalOpen, setProductUpdatesModalOpen] = useState(false); - - const handleCrispWindowShow = () => { - toggleIntercom(!isIntercomToggle); - }; - - return ( - <> - setProductUpdatesModalOpen(false)} /> -
- - - - -
- } - customButtonClassName="relative grid place-items-center rounded-md p-1.5 outline-none" - menuButtonOnClick={() => !isNeedHelpOpen && setIsNeedHelpOpen(true)} - onMenuClose={() => setIsNeedHelpOpen(false)} - placement="top-end" - maxHeight="lg" - closeOnSelect - > - window.open("https://go.plane.so/p-docs", "_blank", "noopener,noreferrer")} - > -
- - {t("documentation")} -
-
- {config?.intercom_app_id && config?.is_intercom_enabled && ( - - - - )} - window.open("mailto:sales@plane.so", "_blank", "noopener,noreferrer")}> -
- - {t("contact_sales")} -
-
-
- - - - - - - window.open("https://go.plane.so/p-discord", "_blank", "noopener,noreferrer")} - > -
- Discord -
-
-
- -
- -
- - ); -}); diff --git a/apps/web/core/components/workspace/sidebar/help-section.tsx b/apps/web/core/components/workspace/sidebar/help-section.tsx deleted file mode 100644 index 38c192379..000000000 --- a/apps/web/core/components/workspace/sidebar/help-section.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import React, { useState } from "react"; -import { observer } from "mobx-react"; -import { HelpCircle, MessagesSquare, MoveLeft, User } from "lucide-react"; -// plane imports -import { useTranslation } from "@plane/i18n"; -import { PageIcon } from "@plane/propel/icons"; -import { Tooltip } from "@plane/propel/tooltip"; -import { CustomMenu } from "@plane/ui"; -import { cn } from "@plane/utils"; -// components -import { ProductUpdatesModal } from "@/components/global"; -// hooks -import { useAppTheme } from "@/hooks/store/use-app-theme"; -import { useInstance } from "@/hooks/store/use-instance"; -import { usePowerK } from "@/hooks/store/use-power-k"; -import { useTransient } from "@/hooks/store/use-transient"; -import { usePlatformOS } from "@/hooks/use-platform-os"; -// plane web components -import { PlaneVersionNumber } from "@/plane-web/components/global"; -import { WorkspaceEditionBadge } from "@/plane-web/components/workspace/edition-badge"; - -export interface WorkspaceHelpSectionProps { - setSidebarActive?: React.Dispatch>; -} - -export const SidebarHelpSection = observer(function SidebarHelpSection(_props: WorkspaceHelpSectionProps) { - // store hooks - const { t } = useTranslation(); - const { sidebarCollapsed: isCollapsed, toggleSidebar, sidebarPeek, toggleSidebarPeek } = useAppTheme(); - const { toggleShortcutsListModal } = usePowerK(); - const { isMobile } = usePlatformOS(); - const { config } = useInstance(); - const { isIntercomToggle, toggleIntercom } = useTransient(); - // states - const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); - const [isProductUpdatesModalOpen, setProductUpdatesModalOpen] = useState(false); - - const handleCrispWindowShow = () => { - toggleIntercom(!isIntercomToggle); - }; - - return ( - <> - setProductUpdatesModalOpen(false)} /> -
-
- - - - -
- } - customButtonClassName="relative grid place-items-center rounded-md p-1.5 outline-none" - menuButtonOnClick={() => !isNeedHelpOpen && setIsNeedHelpOpen(true)} - onMenuClose={() => setIsNeedHelpOpen(false)} - placement="top-end" - maxHeight="lg" - closeOnSelect - > - window.open("https://go.plane.so/p-docs", "_blank")}> -
- - {t("documentation")} -
-
- {config?.intercom_app_id && config?.is_intercom_enabled && ( - - - - )} - window.open("mailto:sales@plane.so", "_blank")}> -
- - {t("contact_sales")} -
-
-
- - - - - - - window.open("https://go.plane.so/p-discord", "_blank")}> -
- Discord -
-
-
- -
- -
-
- -
-
- - - -
-
- - ); -}); diff --git a/apps/web/core/components/workspace/sidebar/help-section/root.tsx b/apps/web/core/components/workspace/sidebar/help-section/root.tsx index 0b2dd8e6c..0fb0b3178 100644 --- a/apps/web/core/components/workspace/sidebar/help-section/root.tsx +++ b/apps/web/core/components/workspace/sidebar/help-section/root.tsx @@ -9,9 +9,8 @@ import { CustomMenu } from "@plane/ui"; import { ProductUpdatesModal } from "@/components/global"; import { AppSidebarItem } from "@/components/sidebar/sidebar-item"; // hooks -import { useInstance } from "@/hooks/store/use-instance"; import { usePowerK } from "@/hooks/store/use-power-k"; -import { useTransient } from "@/hooks/store/use-transient"; +import { useChatSupport } from "@/hooks/use-chat-support"; // plane web components import { PlaneVersionNumber } from "@/plane-web/components/global"; @@ -19,16 +18,11 @@ export const HelpMenuRoot = observer(function HelpMenuRoot() { // store hooks const { t } = useTranslation(); const { toggleShortcutsListModal } = usePowerK(); - const { config } = useInstance(); - const { isIntercomToggle, toggleIntercom } = useTransient(); + const { openChatSupport, isEnabled: isChatSupportEnabled } = useChatSupport(); // states const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); const [isProductUpdatesModalOpen, setProductUpdatesModalOpen] = useState(false); - const handleCrispWindowShow = () => { - toggleIntercom(!isIntercomToggle); - }; - return ( <> setProductUpdatesModalOpen(false)} /> @@ -38,7 +32,7 @@ export const HelpMenuRoot = observer(function HelpMenuRoot() { , + icon: , isActive: isNeedHelpOpen, }} /> @@ -56,11 +50,11 @@ export const HelpMenuRoot = observer(function HelpMenuRoot() { {t("documentation")} - {config?.intercom_app_id && config?.is_intercom_enabled && ( + {isChatSupportEnabled && (