openreplay/frontend/app/components/Client/Integrations/Integrations.tsx
2023-07-04 09:14:56 +02:00

357 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { useModal } from 'App/components/Modal';
import cn from 'classnames';
import { fetch, init } from 'Duck/integrations/actions';
import { fetchIntegrationList, setSiteId } from 'Duck/integrations/integrations';
import SiteDropdown from 'Shared/SiteDropdown';
import ReduxDoc from './ReduxDoc';
import VueDoc from './VueDoc';
import GraphQLDoc from './GraphQLDoc';
import NgRxDoc from './NgRxDoc';
import MobxDoc from './MobxDoc';
import ProfilerDoc from './ProfilerDoc';
import AssistDoc from './AssistDoc';
import PiniaDoc from './PiniaDoc';
import ZustandDoc from './ZustandDoc';
import MSTeams from './Teams';
import DocCard from 'Shared/DocCard/DocCard';
import { PageTitle, Tooltip } from 'UI';
import withPageTitle from 'HOCs/withPageTitle';
import BugsnagForm from './BugsnagForm';
import CloudwatchForm from './CloudwatchForm';
import DatadogForm from './DatadogForm';
import ElasticsearchForm from './ElasticsearchForm';
import GithubForm from './GithubForm';
import IntegrationItem from './IntegrationItem';
import JiraForm from './JiraForm';
import NewrelicForm from './NewrelicForm';
import RollbarForm from './RollbarForm';
import SentryForm from './SentryForm';
import SlackForm from './SlackForm';
import StackdriverForm from './StackdriverForm';
import SumoLogicForm from './SumoLogicForm';
import IntegrationFilters from 'Components/Client/Integrations/IntegrationFilters';
interface Props {
fetch: (name: string, siteId: string) => void;
init: () => void;
fetchIntegrationList: (siteId: any) => void;
integratedList: any;
initialSiteId: string;
setSiteId: (siteId: string) => void;
siteId: string;
hideHeader?: boolean;
loading?: boolean;
}
function Integrations(props: Props) {
const { initialSiteId, hideHeader = false, loading = false } = props;
const { showModal } = useModal();
const [integratedList, setIntegratedList] = useState<string[]>([]);
const [activeFilter, setActiveFilter] = useState<string>('all');
useEffect(() => {
const list = props.integratedList
.filter((item: any) => item.integrated)
.map((item: any) => item.name);
setIntegratedList(list);
}, [props.integratedList]);
useEffect(() => {
props.fetchIntegrationList(initialSiteId);
props.setSiteId(initialSiteId);
}, []);
const onClick = (integration: any, width: number) => {
if (integration.slug && integration.slug !== 'slack' && integration.slug !== 'msteams') {
props.fetch(integration.slug, props.siteId);
}
showModal(
React.cloneElement(integration.component, {
integrated: integratedList.includes(integration.slug)
}),
{ right: true, width }
);
};
const onChangeSelect = ({ value }: any) => {
props.setSiteId(value.value);
props.fetchIntegrationList(value.value);
};
const onChange = (key: string) => {
setActiveFilter(key);
};
const filteredIntegrations = integrations.filter((cat: any) => {
if (activeFilter === 'all') {
return true;
}
return cat.key === activeFilter;
});
const filters = integrations.map((cat: any) => ({
key: cat.key,
title: cat.title,
icon: cat.icon,
}));
return (
<>
<div className='mb-4 p-5 bg-white rounded-lg border'>
{!hideHeader && <PageTitle title={<div>Integrations</div>} />}
<IntegrationFilters onChange={onChange} activeItem={activeFilter} filters={filters}/>
</div>
<div className='mb-4' />
{filteredIntegrations.map((cat: any) => (
<div className='grid grid-cols-3 mt-4 gap-3 auto-cols-max'>
{cat.integrations.map((integration: any) => (
<IntegrationItem
integrated={integratedList.includes(integration.slug)}
integration={integration}
onClick={() =>
onClick(integration, cat.title === 'Plugins' ? 500 : 350)
}
hide={
(integration.slug === 'github' &&
integratedList.includes('jira')) ||
(integration.slug === 'jira' &&
integratedList.includes('github'))
}
/>
))}
</div>
))}
</>
);
}
export default connect(
(state: any) => ({
initialSiteId: state.getIn(['site', 'siteId']),
integratedList: state.getIn(['integrations', 'list']) || [],
loading: state.getIn(['integrations', 'fetchRequest', 'loading']),
siteId: state.getIn(['integrations', 'siteId'])
}),
{ fetch, init, fetchIntegrationList, setSiteId }
)(withPageTitle('Integrations - OpenReplay Preferences')(Integrations));
const integrations = [
{
title: 'Issue Reporting',
key: 'issue-reporting',
description: 'Seamlessly report issues or share issues with your team right from OpenReplay.',
isProject: false,
icon: 'integrations/issue-reporting',
integrations: [
{
title: 'Jira',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'jira',
category: 'Errors',
icon: 'integrations/jira',
component: <JiraForm />
},
{
title: 'Github',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'github',
category: 'Errors',
icon: 'integrations/github',
component: <GithubForm />
},
{
title: 'Slack',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'slack',
category: 'Errors',
icon: 'integrations/slack',
component: <SlackForm />,
shared: true
},
{
title: 'MS Teams',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'msteams',
category: 'Errors',
icon: 'integrations/teams',
component: <MSTeams />,
shared: true
}
]
},
{
title: 'Backend Logging',
key: 'backend-logging',
isProject: true,
description:
'Sync your backend errors with sessions replays and see what happened front-to-back.',
docs: () => (
<DocCard
title='Why use integrations?'
icon='question-lg'
iconBgColor='bg-red-lightest'
iconColor='red'
>
Sync your backend errors with sessions replays and see what happened front-to-back.
</DocCard>
),
integrations: [
{ title: 'Sentry', slug: 'sentry', icon: 'integrations/sentry', component: <SentryForm /> },
{
title: 'Bugsnag',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'bugsnag',
icon: 'integrations/bugsnag',
component: <BugsnagForm />
},
{
title: 'Rollbar',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'rollbar',
icon: 'integrations/rollbar',
component: <RollbarForm />
},
{
title: 'Elasticsearch',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'elasticsearch',
icon: 'integrations/elasticsearch',
component: <ElasticsearchForm />
},
{
title: 'Datadog',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'datadog',
icon: 'integrations/datadog',
component: <DatadogForm />
},
{
title: 'Sumo Logic',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'sumologic',
icon: 'integrations/sumologic',
component: <SumoLogicForm />
},
{
title: 'Stackdriver',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'stackdriver',
icon: 'integrations/google-cloud',
component: <StackdriverForm />
},
{
title: 'CloudWatch',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'cloudwatch',
icon: 'integrations/aws',
component: <CloudwatchForm />
},
{
title: 'Newrelic',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
slug: 'newrelic',
icon: 'integrations/newrelic',
component: <NewrelicForm />
}
]
},
{
title: 'Collaboration',
key: 'collaboration',
isProject: false,
description: 'Share your sessions with your team and collaborate on issues.',
integrations: []
},
{
title: 'State Management',
key: 'state-management',
isProject: true,
description: 'Sync your Redux or VueX store with sessions replays and see what happened front-to-back.',
integrations: []
},
{
title: 'Plugins',
key: 'plugins',
isProject: true,
docs: () => (
<DocCard
title='What are plugins?'
icon='question-lg'
iconBgColor='bg-red-lightest'
iconColor='red'
>
Plugins capture your applications store, monitor queries, track performance issues and even
assist your end user through live sessions.
</DocCard>
),
description:
'Reproduce issues as if they happened in your own browser. Plugins help capture your application\'s store, HTTP requeets, GraphQL queries, and more.',
integrations: [
{
title: 'Redux',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/redux', component: <ReduxDoc />
},
{
title: 'VueX',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/vuejs',
component: <VueDoc />
},
{
title: 'Pinia',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/pinia',
component: <PiniaDoc />
},
{
title: 'GraphQL',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/graphql',
component: <GraphQLDoc />
},
{
title: 'NgRx',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/ngrx',
component: <NgRxDoc />
},
{
title: 'MobX',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/mobx',
component: <MobxDoc />
},
{
title: 'Profiler',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/openreplay',
component: <ProfilerDoc />
},
{
title: 'Assist',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: 'integrations/openreplay',
component: <AssistDoc />
},
{
title: 'Zustand',
subtitle: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
icon: '',
header: '🐻',
component: <ZustandDoc />
}
]
}
];