feat: integration: added copy test tracking, facing issue btn and request more integration section (#5130)

* feat: integration: added copy test tracking, facing issue btn and request more integration section

* feat: removed copy btn tracking from onboarding markdown

* feat: removed copy btn tracking from onboarding markdown

* feat: added track event on Configure option clicks

* feat: code cleanup

* feat: code cleanup

* feat: changed trackEvent to logEvent

* feat: changed text in integration facing issue button

* feat: sliced copied text

* feat: code cleanup
This commit is contained in:
SagarRajput-7 2024-06-05 19:35:03 +05:30 committed by GitHub
parent 6a829489a8
commit 694f2562bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 72 additions and 10 deletions

View File

@ -1,25 +1,33 @@
/* eslint-disable prefer-destructuring */
import './CodeCopyBtn.scss'; import './CodeCopyBtn.scss';
import { CheckOutlined, CopyOutlined } from '@ant-design/icons'; import { CheckOutlined, CopyOutlined } from '@ant-design/icons';
import cx from 'classnames'; import cx from 'classnames';
import { useState } from 'react'; import React, { useState } from 'react';
export default function CodeCopyBtn({ function CodeCopyBtn({
children, children,
onCopyClick,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
onCopyClick?: (additionalInfo?: Record<string, unknown>) => void;
}): JSX.Element { }): JSX.Element {
const [isSnippetCopied, setIsSnippetCopied] = useState(false); const [isSnippetCopied, setIsSnippetCopied] = useState(false);
const handleClick = (): void => { const handleClick = (): void => {
let copiedText = '';
if (children && Array.isArray(children)) { if (children && Array.isArray(children)) {
setIsSnippetCopied(true); setIsSnippetCopied(true);
navigator.clipboard.writeText(children[0].props.children[0]).finally(() => { 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(() => { setTimeout(() => {
setIsSnippetCopied(false); setIsSnippetCopied(false);
}, 1000); }, 1000);
}); });
copiedText = (children[0].props.children[0] as string).slice(0, 200);
} }
onCopyClick?.({ copiedText });
}; };
return ( return (
@ -30,3 +38,9 @@ export default function CodeCopyBtn({
</div> </div>
); );
} }
CodeCopyBtn.defaultProps = {
onCopyClick: (): void => {},
};
export default CodeCopyBtn;

View File

@ -2,6 +2,8 @@
/* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable @typescript-eslint/explicit-function-return-type */ /* 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 ReactMarkdown from 'react-markdown';
import { CodeProps } from 'react-markdown/lib/ast-to-react'; import { CodeProps } from 'react-markdown/lib/ast-to-react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
@ -15,10 +17,28 @@ interface LinkProps {
children: React.ReactElement; children: React.ReactElement;
} }
function Pre({ children }: { children: React.ReactNode }): JSX.Element { function Pre({
children,
elementDetails,
trackCopyAction,
}: {
children: React.ReactNode;
trackCopyAction: boolean;
elementDetails: Record<string, unknown>;
}): JSX.Element {
const { trackingTitle = '', ...rest } = elementDetails;
const handleClick = (additionalInfo?: Record<string, unknown>): void => {
const trackingData = { ...rest, copiedContent: additionalInfo };
if (trackCopyAction && !isEmpty(trackingTitle)) {
logEvent(trackingTitle as string, trackingData);
}
};
return ( return (
<pre className="code-snippet-container"> <pre className="code-snippet-container">
<CodeCopyBtn>{children}</CodeCopyBtn> <CodeCopyBtn onCopyClick={handleClick}>{children}</CodeCopyBtn>
{children} {children}
</pre> </pre>
); );
@ -83,9 +103,13 @@ function CustomTag({ color }: { color: string }): JSX.Element {
function MarkdownRenderer({ function MarkdownRenderer({
markdownContent, markdownContent,
variables, variables,
trackCopyAction,
elementDetails,
}: { }: {
markdownContent: any; markdownContent: any;
variables: any; variables: any;
trackCopyAction?: boolean;
elementDetails?: Record<string, unknown>;
}): JSX.Element { }): JSX.Element {
const interpolatedMarkdown = interpolateMarkdown(markdownContent, variables); const interpolatedMarkdown = interpolateMarkdown(markdownContent, variables);
@ -96,7 +120,12 @@ function MarkdownRenderer({
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
a: Link, a: Link,
pre: Pre, pre: ({ children }) =>
Pre({
children,
elementDetails: elementDetails ?? {},
trackCopyAction: !!trackCopyAction,
}),
code: Code, code: Code,
customtag: CustomTag, customtag: CustomTag,
}} }}
@ -106,4 +135,9 @@ function MarkdownRenderer({
); );
} }
MarkdownRenderer.defaultProps = {
elementDetails: {},
trackCopyAction: false,
};
export { Code, Link, MarkdownRenderer, Pre }; export { Code, Link, MarkdownRenderer, Pre };

View File

@ -1,6 +1,7 @@
import './IntegrationDetailContentTabs.styles.scss'; import './IntegrationDetailContentTabs.styles.scss';
import { Button, Typography } from 'antd'; import { Button, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import cx from 'classnames'; import cx from 'classnames';
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer'; import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
import useAnalytics from 'hooks/analytics/useAnalytics'; import useAnalytics from 'hooks/analytics/useAnalytics';
@ -17,12 +18,16 @@ function Configure(props: ConfigurationProps): JSX.Element {
const { configuration, integrationId } = props; const { configuration, integrationId } = props;
const [selectedConfigStep, setSelectedConfigStep] = useState(0); const [selectedConfigStep, setSelectedConfigStep] = useState(0);
const handleMenuClick = (index: number): void => {
setSelectedConfigStep(index);
};
const { trackEvent } = useAnalytics(); const { trackEvent } = useAnalytics();
const handleMenuClick = (index: number, config: any): void => {
setSelectedConfigStep(index);
logEvent('Integrations Detail Page: Configure tab', {
sectionName: config?.title,
integrationId,
});
};
useEffect(() => { useEffect(() => {
trackEvent( trackEvent(
INTEGRATION_TELEMETRY_EVENTS.INTEGRATIONS_DETAIL_CONFIGURE_INSTRUCTION, 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 // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
const markdownDetailsForTracking = {
trackingTitle: `Integrations Detail Page: Copy button`,
sectionName: configuration[selectedConfigStep].title,
integrationId,
};
return ( return (
<div className="integration-detail-configure"> <div className="integration-detail-configure">
<div className="configure-menu"> <div className="configure-menu">
@ -43,7 +54,7 @@ function Configure(props: ConfigurationProps): JSX.Element {
className={cx('configure-menu-item', { className={cx('configure-menu-item', {
active: selectedConfigStep === index, active: selectedConfigStep === index,
})} })}
onClick={(): void => handleMenuClick(index)} onClick={(): void => handleMenuClick(index, config)}
> >
<Typography.Text className="configure-text"> <Typography.Text className="configure-text">
{config.title} {config.title}
@ -55,6 +66,8 @@ function Configure(props: ConfigurationProps): JSX.Element {
<MarkdownRenderer <MarkdownRenderer
variables={{}} variables={{}}
markdownContent={configuration[selectedConfigStep].instructions} markdownContent={configuration[selectedConfigStep].instructions}
elementDetails={markdownDetailsForTracking}
trackCopyAction
/> />
</div> </div>
</div> </div>

View File

@ -24,6 +24,7 @@ function Overview(props: OverviewProps): JSX.Element {
]; ];
const assetLabelMap = ['Pipelines', 'Dashboards', 'Alerts']; const assetLabelMap = ['Pipelines', 'Dashboards', 'Alerts'];
return ( return (
<div className="integration-detail-overview"> <div className="integration-detail-overview">
<div className="integration-detail-overview-left-container"> <div className="integration-detail-overview-left-container">