From d45347da2b4226b816857bf0e8a5528428a196a9 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Fri, 7 Feb 2025 16:47:21 +0100 Subject: [PATCH] fix(ui): session share modal fetch list and modal component --- .../MobilePlayer/MobilePlayerSubheader.tsx | 41 ++- .../app/components/Session_/Subheader.tsx | 34 +- .../shared/SharePopup/SharePopup.tsx | 331 +++++++++--------- 3 files changed, 197 insertions(+), 209 deletions(-) diff --git a/frontend/app/components/Session/Player/MobilePlayer/MobilePlayerSubheader.tsx b/frontend/app/components/Session/Player/MobilePlayer/MobilePlayerSubheader.tsx index c33ee9abb..dec449f06 100644 --- a/frontend/app/components/Session/Player/MobilePlayer/MobilePlayerSubheader.tsx +++ b/frontend/app/components/Session/Player/MobilePlayer/MobilePlayerSubheader.tsx @@ -3,17 +3,22 @@ import QueueControls from 'Components/Session_/QueueControls'; import Bookmark from 'Shared/Bookmark'; import Issues from 'Components/Session_/Issues/Issues'; import NotePopup from 'Components/Session_/components/NotePopup'; -import { Tag } from 'antd' +import { Tag } from 'antd'; import { ShareAltOutlined } from '@ant-design/icons'; -import { Button as AntButton, Popover } from 'antd'; -import SharePopup from 'Components/shared/SharePopup/SharePopup'; +import { Button as AntButton } from 'antd'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; +import ShareModal from 'Shared/SharePopup/SharePopup'; +import { Tooltip } from '.store/antd-virtual-7db13b4af6/package'; +import { useModal } from 'Components/ModalContext'; +import { PlayerContext } from 'Components/Session/playerContext'; function SubHeader(props: any) { - const { sessionStore, integrationsStore} = useStore(); + const { sessionStore, integrationsStore } = useStore(); const integrations = integrationsStore.issues.list; const isIOS = sessionStore.current.platform === 'ios'; + const { openModal, closeModal } = useModal(); + const { store } = React.useContext(PlayerContext); const enabledIntegration = useMemo(() => { if (!integrations || !integrations.length) { @@ -26,7 +31,7 @@ function SubHeader(props: any) { return ( <>
- {isIOS ? 'iOS' : 'Android'} BETA + {isIOS ? 'iOS' : 'Android'} BETA
{enabledIntegration && } - - - - - - -
- } - /> + + openModal( + , + { title: 'Share Session' } + )} + > + + +
{/* @ts-ignore */} diff --git a/frontend/app/components/Session_/Subheader.tsx b/frontend/app/components/Session_/Subheader.tsx index 7bd1413e4..b3efe5863 100644 --- a/frontend/app/components/Session_/Subheader.tsx +++ b/frontend/app/components/Session_/Subheader.tsx @@ -1,7 +1,6 @@ import { ShareAltOutlined } from '@ant-design/icons'; import { Button as AntButton, Switch, Tooltip, Dropdown } from 'antd'; import cn from 'classnames'; -import IssuesModal from 'Components/Session_/Issues/IssuesModal'; import { Link2, Keyboard } from 'lucide-react'; import { observer } from 'mobx-react-lite'; import React, { useMemo } from 'react'; @@ -17,11 +16,11 @@ import WarnBadge from 'Components/Session_/WarnBadge'; import { toast } from 'react-toastify'; import HighlightButton from './Highlight/HighlightButton'; -import SharePopup from '../shared/SharePopup/SharePopup'; import QueueControls from './QueueControls'; import { Bookmark as BookmarkIcn, BookmarkCheck, Vault } from 'lucide-react'; import { useModal } from 'Components/ModalContext'; import IssueForm from 'Components/Session_/Issues/IssueForm'; +import ShareModal from '../shared/SharePopup/SharePopup'; const disableDevtools = 'or_devtools_uxt_toggle'; @@ -132,7 +131,7 @@ function SubHeader(props) { @@ -145,21 +144,20 @@ function SubHeader(props) { )} style={{ width: 'max-content' }} > - - - - - - -
- } - /> + + openModal( + , + { title: 'Share Session' } + )} + > + + + props.setActiveTab('HIGHLIGHT')} /> { - const { store } = React.useContext(PlayerContext); - const { showModal, hideModal } = useModal(); - const openModal = () => { - showModal( - , - { right: true, width: 300 } - ); - }; - - return ( -
- {trigger} -
- ); -}; - - interface Props { showCopyLink?: boolean; hideModal: () => void; time: number; } -function ShareModalComp({ - showCopyLink, - hideModal, - time, -}: Props) { - const { integrationsStore, sessionStore, userStore } = useStore(); - const sessionId = sessionStore.current.sessionId - const channels = integrationsStore.slack.list; +const ShareModalComp: React.FC = ({ showCopyLink, hideModal, time }) => { + const { integrationsStore, sessionStore } = useStore(); + const sessionId = sessionStore.current.sessionId; + const slackChannels: Channel[] = integrationsStore.slack.list || []; + const msTeamsChannels: Channel[] = integrationsStore.msteams.list || []; const slackLoaded = integrationsStore.slack.loaded; - const msTeamsChannels = integrationsStore.msteams.list; const msTeamsLoaded = integrationsStore.msteams.loaded; const fetchSlack = integrationsStore.slack.fetchIntegrations; const fetchTeams = integrationsStore.msteams.fetchIntegrations; const sendSlackMsg = integrationsStore.slack.sendMessage; const sendMsTeamsMsg = integrationsStore.msteams.sendMessage; - const [shareTo, setShareTo] = useState('slack'); + const [shareTo, setShareTo] = useState<'slack' | 'teams'>('slack'); const [comment, setComment] = useState(''); - // @ts-ignore - const [channelId, setChannelId] = useState(channels[0]?.webhookId); - // @ts-ignore - const [teamsChannel, setTeamsChannel] = useState(msTeamsChannels[0]?.webhookId); + const [channelId, setChannelId] = useState(slackChannels[0]?.webhookId); + const [teamsChannel, setTeamsChannel] = useState(msTeamsChannels[0]?.webhookId); const [loadingSlack, setLoadingSlack] = useState(false); const [loadingTeams, setLoadingTeams] = useState(false); - const isLoading = loadingSlack || loadingTeams; + useEffect(() => { + if (slackChannels.length === 0 && !slackLoaded) void fetchSlack(); + }, [slackChannels, slackLoaded, fetchSlack]); useEffect(() => { - // @ts-ignore - if (channels.size === 0 && !slackLoaded) { - fetchSlack(); + if (msTeamsChannels.length === 0 && !msTeamsLoaded) void fetchTeams(); + }, [msTeamsChannels, msTeamsLoaded, fetchTeams]); + + useEffect(() => { + if (slackChannels.length && !channelId) { + setChannelId(slackChannels[0].webhookId); } - // @ts-ignore - if (msTeamsChannels.size === 0 && !msTeamsLoaded) { - fetchTeams(); + }, [slackChannels, channelId]); + + useEffect(() => { + if (msTeamsChannels.length && !teamsChannel) { + setTeamsChannel(msTeamsChannels[0].webhookId); } - }, [channels, slackLoaded, msTeamsChannels, msTeamsLoaded, fetchSlack, fetchTeams]); + }, [msTeamsChannels, teamsChannel]); const editMessage = (e: React.ChangeEvent) => setComment(e.target.value); - const shareToSlack = () => { + + const shareToSlack = async () => { + if (!channelId) return; setLoadingSlack(true); - void sendSlackMsg({ - integrationId: channelId, - entity: 'sessions', - entityId: sessionId, - data: { comment }, - }).then(() => handleSuccess('Slack')); - }; - - const shareToMSTeams = () => { - setLoadingTeams(true); - sendMsTeamsMsg({ - integrationId: teamsChannel, - entity: 'sessions', - entityId: sessionId, - data: { comment }, - }).then(() => handleSuccess('MS Teams')); - }; - - const handleSuccess = (endpoint: string) => { - if (endpoint === 'Slack') { + try { + await sendSlackMsg({ + integrationId: channelId, + entity: 'sessions', + entityId: sessionId, + data: { comment } + }); + toast.success('Sent to Slack.'); + } catch { + toast.error('Failed to send to Slack.'); + } finally { setLoadingSlack(false); - } else { + } + }; + + const shareToMSTeams = async () => { + if (!teamsChannel) return; + setLoadingTeams(true); + try { + await sendMsTeamsMsg({ + integrationId: teamsChannel, + entity: 'sessions', + entityId: sessionId, + data: { comment } + }); + toast.success('Sent to MS Teams.'); + } catch { + toast.error('Failed to send to MS Teams.'); + } finally { setLoadingTeams(false); } - // @ts-ignore - toast.success(`Sent to ${endpoint}.`); }; - const changeSlackChannel = (value: any) => setChannelId(value.value); - const changeTeamsChannel = (value: any) => setTeamsChannel(value.value); + const changeSlackChannel = (value: string) => setChannelId(value); + const changeTeamsChannel = (value: string) => setTeamsChannel(value); - const slackOptions = channels - .map(({ webhookId, name }) => ({ - value: webhookId, - label: name, - })) + const slackOptions = useMemo( + () => + slackChannels.map(({ webhookId, name }) => ({ + value: webhookId, + label: name + })), + [slackChannels] + ); - const msTeamsOptions = msTeamsChannels - .map(({ webhookId, name }) => ({ - value: webhookId, - label: name, - })) + const msTeamsOptions = useMemo( + () => + msTeamsChannels.map(({ webhookId, name }) => ({ + value: webhookId, + label: name + })), + [msTeamsChannels] + ); - const sendMsg = () => { - if (shareTo === 'slack') { - shareToSlack(); - } else { - shareToMSTeams(); - } + const sendMsg = async () => { + shareTo === 'slack' ? await shareToSlack() : await shareToMSTeams(); hideModal(); - } + }; + const hasBoth = slackOptions.length > 0 && msTeamsOptions.length > 0; const hasNothing = slackOptions.length === 0 && msTeamsOptions.length === 0; + const isLoading = loadingSlack || loadingTeams; + + const handleSegmentChange = (value: string) => { + const newShareTo = value as 'slack' | 'teams'; + setShareTo(newShareTo); + if (newShareTo === 'slack' && slackOptions.length > 0) { + setChannelId(slackOptions[0].value); + } else if (newShareTo === 'teams' && msTeamsOptions.length > 0) { + setTeamsChannel(msTeamsOptions[0].value); + } + }; + return ( -
+
{isLoading ? ( ) : ( <> -
- -
Share Session
-
{!hasNothing ? ( -
-
-
-
- Share via -
+ <> +
+ {hasBoth ? ( - -
Slack
-
, - value: 'slack', + label: ( +
+ +
Slack
+
+ ), + value: 'slack' }, { - label:
- -
MS Teams
-
, - value: 'teams', - }, + label: ( +
+ +
MS Teams
+
+ ), + value: 'teams' + } ]} - onChange={(value) => setShareTo(value as 'slack' | 'teams')} + onChange={handleSegmentChange} + value={shareTo} /> ) : ( -
+
0 - ? 'integrations/slack-bw' - : 'integrations/teams-white' - } + name={slackOptions.length > 0 ? 'integrations/slack-bw' : 'integrations/teams-white'} size={16} />
{slackOptions.length > 0 ? 'Slack' : 'MS Teams'}
)} -
+ -
-
Select a channel or individual
+ {shareTo === 'slack' ? ( - + {slackOptions.map(({ value, label }) => ( + + {label} + + ))} + ) : ( - + {msTeamsOptions.map(({ value, label }) => ( + + {label} + + ))} + )} -
+ -
-
Message
-