diff --git a/frontend/src/components/MarkdownRenderer/CodeCopyBtn/CodeCopyBtn.tsx b/frontend/src/components/MarkdownRenderer/CodeCopyBtn/CodeCopyBtn.tsx index e23882cc71..b098c4228e 100644 --- a/frontend/src/components/MarkdownRenderer/CodeCopyBtn/CodeCopyBtn.tsx +++ b/frontend/src/components/MarkdownRenderer/CodeCopyBtn/CodeCopyBtn.tsx @@ -1,25 +1,33 @@ +/* eslint-disable prefer-destructuring */ import './CodeCopyBtn.scss'; import { CheckOutlined, CopyOutlined } from '@ant-design/icons'; import cx from 'classnames'; -import { useState } from 'react'; +import React, { useState } from 'react'; -export default function CodeCopyBtn({ +function CodeCopyBtn({ children, + onCopyClick, }: { children: React.ReactNode; + onCopyClick?: (additionalInfo?: Record) => void; }): JSX.Element { const [isSnippetCopied, setIsSnippetCopied] = useState(false); const handleClick = (): void => { + let copiedText = ''; if (children && Array.isArray(children)) { setIsSnippetCopied(true); navigator.clipboard.writeText(children[0].props.children[0]).finally(() => { + copiedText = (children[0].props.children[0] as string).slice(0, 200); // slicing is done due to the limitation in accepted char length in attributes setTimeout(() => { setIsSnippetCopied(false); }, 1000); }); + copiedText = (children[0].props.children[0] as string).slice(0, 200); } + + onCopyClick?.({ copiedText }); }; return ( @@ -30,3 +38,9 @@ export default function CodeCopyBtn({ ); } + +CodeCopyBtn.defaultProps = { + onCopyClick: (): void => {}, +}; + +export default CodeCopyBtn; diff --git a/frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx b/frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx index 20be0677bd..3b20454ac5 100644 --- a/frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx +++ b/frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx @@ -2,6 +2,8 @@ /* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ +import logEvent from 'api/common/logEvent'; +import { isEmpty } from 'lodash-es'; import ReactMarkdown from 'react-markdown'; import { CodeProps } from 'react-markdown/lib/ast-to-react'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; @@ -15,10 +17,28 @@ interface LinkProps { children: React.ReactElement; } -function Pre({ children }: { children: React.ReactNode }): JSX.Element { +function Pre({ + children, + elementDetails, + trackCopyAction, +}: { + children: React.ReactNode; + trackCopyAction: boolean; + elementDetails: Record; +}): JSX.Element { + const { trackingTitle = '', ...rest } = elementDetails; + + const handleClick = (additionalInfo?: Record): void => { + const trackingData = { ...rest, copiedContent: additionalInfo }; + + if (trackCopyAction && !isEmpty(trackingTitle)) { + logEvent(trackingTitle as string, trackingData); + } + }; + return (
-			{children}
+			{children}
 			{children}
 		
); @@ -83,9 +103,13 @@ function CustomTag({ color }: { color: string }): JSX.Element { function MarkdownRenderer({ markdownContent, variables, + trackCopyAction, + elementDetails, }: { markdownContent: any; variables: any; + trackCopyAction?: boolean; + elementDetails?: Record; }): JSX.Element { const interpolatedMarkdown = interpolateMarkdown(markdownContent, variables); @@ -96,7 +120,12 @@ function MarkdownRenderer({ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore a: Link, - pre: Pre, + pre: ({ children }) => + Pre({ + children, + elementDetails: elementDetails ?? {}, + trackCopyAction: !!trackCopyAction, + }), code: Code, customtag: CustomTag, }} @@ -106,4 +135,9 @@ function MarkdownRenderer({ ); } +MarkdownRenderer.defaultProps = { + elementDetails: {}, + trackCopyAction: false, +}; + export { Code, Link, MarkdownRenderer, Pre }; diff --git a/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Configure.tsx b/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Configure.tsx index 2984ba40fe..f645653883 100644 --- a/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Configure.tsx +++ b/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Configure.tsx @@ -1,6 +1,7 @@ import './IntegrationDetailContentTabs.styles.scss'; import { Button, Typography } from 'antd'; +import logEvent from 'api/common/logEvent'; import cx from 'classnames'; import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer'; import useAnalytics from 'hooks/analytics/useAnalytics'; @@ -17,12 +18,16 @@ function Configure(props: ConfigurationProps): JSX.Element { const { configuration, integrationId } = props; const [selectedConfigStep, setSelectedConfigStep] = useState(0); - const handleMenuClick = (index: number): void => { - setSelectedConfigStep(index); - }; - const { trackEvent } = useAnalytics(); + const handleMenuClick = (index: number, config: any): void => { + setSelectedConfigStep(index); + logEvent('Integrations Detail Page: Configure tab', { + sectionName: config?.title, + integrationId, + }); + }; + useEffect(() => { trackEvent( INTEGRATION_TELEMETRY_EVENTS.INTEGRATIONS_DETAIL_CONFIGURE_INSTRUCTION, @@ -33,6 +38,12 @@ function Configure(props: ConfigurationProps): JSX.Element { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const markdownDetailsForTracking = { + trackingTitle: `Integrations Detail Page: Copy button`, + sectionName: configuration[selectedConfigStep].title, + integrationId, + }; + return (
@@ -43,7 +54,7 @@ function Configure(props: ConfigurationProps): JSX.Element { className={cx('configure-menu-item', { active: selectedConfigStep === index, })} - onClick={(): void => handleMenuClick(index)} + onClick={(): void => handleMenuClick(index, config)} > {config.title} @@ -55,6 +66,8 @@ function Configure(props: ConfigurationProps): JSX.Element {
diff --git a/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Overview.tsx b/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Overview.tsx index 5160115e12..03ea177dd4 100644 --- a/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Overview.tsx +++ b/frontend/src/pages/Integrations/IntegrationDetailPage/IntegrationDetailContentTabs/Overview.tsx @@ -24,6 +24,7 @@ function Overview(props: OverviewProps): JSX.Element { ]; const assetLabelMap = ['Pipelines', 'Dashboards', 'Alerts']; + return (