From 48145e5a70356eeaccacf90a01ab4726d30a371b Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Fri, 27 Jan 2023 19:13:59 +0100 Subject: [PATCH] fix(ui) - integration form --- .../Client/Integrations/IntegrationForm.js | 23 +- .../Client/Integrations/Integrations.tsx | 365 +++++++++++------- .../Client/Integrations/JiraForm/JiraForm.js | 67 ++-- 3 files changed, 267 insertions(+), 188 deletions(-) diff --git a/frontend/app/components/Client/Integrations/IntegrationForm.js b/frontend/app/components/Client/Integrations/IntegrationForm.js index cdde52bd9..c4d634562 100644 --- a/frontend/app/components/Client/Integrations/IntegrationForm.js +++ b/frontend/app/components/Client/Integrations/IntegrationForm.js @@ -70,29 +70,18 @@ export default class IntegrationForm extends React.PureComponent { remove = () => { const { name, config, ignoreProject } = this.props; - this.props.remove(name, !ignoreProject ? config.projectId : null).then( - function () { - this.props.onClose(); - this.fetchList(); - }.bind(this) - ); + this.props.remove(name, !ignoreProject ? config.projectId : null).then(() => { + this.props.onClose(); + this.fetchList(); + }); }; render() { - const { config, saving, removing, formFields, name, loading, ignoreProject } = this.props; - // const { currentSiteId } = this.state; - + const { config, saving, removing, formFields, name, loading, integrated } = this.props; return (
- {/* {!ignoreProject && ( - - - - - )} */} - {formFields.map( ({ key, @@ -140,7 +129,7 @@ export default class IntegrationForm extends React.PureComponent { {config.exists() ? 'Update' : 'Add'} - {config.exists() && ( + {integrated && ( diff --git a/frontend/app/components/Client/Integrations/Integrations.tsx b/frontend/app/components/Client/Integrations/Integrations.tsx index abbd506ea..d1f53f56d 100644 --- a/frontend/app/components/Client/Integrations/Integrations.tsx +++ b/frontend/app/components/Client/Integrations/Integrations.tsx @@ -27,159 +27,244 @@ import AssistDoc from './AssistDoc'; import { PageTitle, Tooltip } from 'UI'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; import withPageTitle from 'HOCs/withPageTitle'; -import PiniaDoc from './PiniaDoc' -import ZustandDoc from './ZustandDoc' -import MSTeams from './Teams' +import PiniaDoc from './PiniaDoc'; +import ZustandDoc from './ZustandDoc'; +import MSTeams from './Teams'; 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; + 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] = React.useState([]); + const { initialSiteId, hideHeader = false, loading = false } = props; + const { showModal } = useModal(); + const [integratedList, setIntegratedList] = React.useState([]); - useEffect(() => { - const list = props.integratedList.filter((item: any) => item.integrated).map((item: any) => item.name); - setIntegratedList(list); - }, [props.integratedList]); + useEffect(() => { + const list = props.integratedList + .filter((item: any) => item.integrated) + .map((item: any) => item.name); + setIntegratedList(list); + }, [props.integratedList]); - useEffect(() => { - if (!props.siteId) { - props.setSiteId(initialSiteId); - props.fetchIntegrationList(initialSiteId); - } else { - props.fetchIntegrationList(props.siteId); - } - }, []); + useEffect(() => { + if (!props.siteId) { + props.setSiteId(initialSiteId); + props.fetchIntegrationList(initialSiteId); + } else { + props.fetchIntegrationList(props.siteId); + } + }, []); - const onClick = (integration: any, width: number) => { - if (integration.slug) { - props.fetch(integration.slug, props.siteId); - } - showModal(integration.component, { right: true, width }); - }; + const onClick = (integration: any, width: number) => { + if (integration.slug) { + props.fetch(integration.slug, props.siteId); + } - const onChangeSelect = ({ value }: any) => { - props.setSiteId(value.value); - props.fetchIntegrationList(value.value); - }; - - return ( -
- {!hideHeader && Integrations
} />} - {integrations.map((cat: any) => ( -
-
-

{cat.title}

- {cat.isProject && ( -
-
- -
- {loading && cat.isProject && } -
- )} -
-
{cat.description}
- -
- {cat.integrations.map((integration: any) => ( - - - onClick(integration, cat.title === "Plugins" ? 500 : 350)} - hide={ - (integration.slug === 'github' && integratedList.includes('jira')) || - (integration.slug === 'jira' && integratedList.includes('github')) - } - /> - - - ))} -
-
- ))} -
+ 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); + }; + + return ( +
+ {!hideHeader && Integrations
} />} + {integrations.map((cat: any) => ( +
+
+

{cat.title}

+ {cat.isProject && ( +
+
+ +
+ {loading && cat.isProject && } +
+ )} +
+
{cat.description}
+ +
+ {cat.integrations.map((integration: any) => ( + + + onClick(integration, cat.title === 'Plugins' ? 500 : 350)} + hide={ + (integration.slug === 'github' && integratedList.includes('jira')) || + (integration.slug === 'jira' && integratedList.includes('github')) + } + /> + + + ))} +
+
+ ))} + + ); } 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 } + (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 and Collaborations', - key: 1, - description: 'Seamlessly report issues or share issues with your team right from OpenReplay.', - isProject: false, - integrations: [ - { title: 'Jira', slug: 'jira', category: 'Errors', icon: 'integrations/jira', component: }, - { title: 'Github', slug: 'github', category: 'Errors', icon: 'integrations/github', component: }, - { title: 'Slack', slug: 'slack', category: 'Errors', icon: 'integrations/slack', component: , shared: true }, - { title: 'MS Teams', slug: 'msteams', category: 'Errors', icon: 'integrations/teams', component: , shared: true }, - ], - }, - { - title: 'Backend Logging', - key: 2, - isProject: true, - description: 'Sync your backend errors with sessions replays and see what happened front-to-back.', - integrations: [ - { title: 'Sentry', slug: 'sentry', icon: 'integrations/sentry', component: }, - { title: 'Bugsnag', slug: 'bugsnag', icon: 'integrations/bugsnag', component: }, - { title: 'Rollbar', slug: 'rollbar', icon: 'integrations/rollbar', component: }, - { title: 'Elasticsearch', slug: 'elasticsearch', icon: 'integrations/elasticsearch', component: }, - { title: 'Datadog', slug: 'datadog', icon: 'integrations/datadog', component: }, - { title: 'Sumo Logic', slug: 'sumologic', icon: 'integrations/sumologic', component: }, - { - title: 'Stackdriver', - slug: 'stackdriver', - icon: 'integrations/google-cloud', - component: , - }, - { title: 'CloudWatch', slug: 'cloudwatch', icon: 'integrations/aws', component: }, - { title: 'Newrelic', slug: 'newrelic', icon: 'integrations/newrelic', component: }, - ], - }, - { - title: 'Plugins', - key: 3, - isProject: true, - 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', slug: 'redux', icon: 'integrations/redux', component: }, - { title: 'VueX', slug: 'vuex', icon: 'integrations/vuejs', component: }, - { title: 'Pinia', slug: 'pinia', icon: 'integrations/pinia', component: }, - { title: 'GraphQL', slug: 'graphql', icon: 'integrations/graphql', component: }, - { title: 'NgRx', slug: 'ngrx', icon: 'integrations/ngrx', component: }, - { title: 'MobX', slug: 'mobx', icon: 'integrations/mobx', component: }, - { title: 'Profiler', slug: 'profiler', icon: 'integrations/openreplay', component: }, - { title: 'Assist', slug: 'assist', icon: 'integrations/openreplay', component: }, - { title: 'Zustand', slug: 'zustand', icon: '', header: '🐻', component: } - ], - }, + { + title: 'Issue Reporting and Collaborations', + key: 1, + description: 'Seamlessly report issues or share issues with your team right from OpenReplay.', + isProject: false, + integrations: [ + { + title: 'Jira', + slug: 'jira', + category: 'Errors', + icon: 'integrations/jira', + component: , + }, + { + title: 'Github', + slug: 'github', + category: 'Errors', + icon: 'integrations/github', + component: , + }, + { + title: 'Slack', + slug: 'slack', + category: 'Errors', + icon: 'integrations/slack', + component: , + shared: true, + }, + { + title: 'MS Teams', + slug: 'msteams', + category: 'Errors', + icon: 'integrations/teams', + component: , + shared: true, + }, + ], + }, + { + title: 'Backend Logging', + key: 2, + isProject: true, + description: + 'Sync your backend errors with sessions replays and see what happened front-to-back.', + integrations: [ + { title: 'Sentry', slug: 'sentry', icon: 'integrations/sentry', component: }, + { + title: 'Bugsnag', + slug: 'bugsnag', + icon: 'integrations/bugsnag', + component: , + }, + { + title: 'Rollbar', + slug: 'rollbar', + icon: 'integrations/rollbar', + component: , + }, + { + title: 'Elasticsearch', + slug: 'elasticsearch', + icon: 'integrations/elasticsearch', + component: , + }, + { + title: 'Datadog', + slug: 'datadog', + icon: 'integrations/datadog', + component: , + }, + { + title: 'Sumo Logic', + slug: 'sumologic', + icon: 'integrations/sumologic', + component: , + }, + { + title: 'Stackdriver', + slug: 'stackdriver', + icon: 'integrations/google-cloud', + component: , + }, + { + title: 'CloudWatch', + slug: 'cloudwatch', + icon: 'integrations/aws', + component: , + }, + { + title: 'Newrelic', + slug: 'newrelic', + icon: 'integrations/newrelic', + component: , + }, + ], + }, + { + title: 'Plugins', + key: 3, + isProject: true, + 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', slug: 'redux', icon: 'integrations/redux', component: }, + { title: 'VueX', slug: 'vuex', icon: 'integrations/vuejs', component: }, + { title: 'Pinia', slug: 'pinia', icon: 'integrations/pinia', component: }, + { + title: 'GraphQL', + slug: 'graphql', + icon: 'integrations/graphql', + component: , + }, + { title: 'NgRx', slug: 'ngrx', icon: 'integrations/ngrx', component: }, + { title: 'MobX', slug: 'mobx', icon: 'integrations/mobx', component: }, + { + title: 'Profiler', + slug: 'profiler', + icon: 'integrations/openreplay', + component: , + }, + { + title: 'Assist', + slug: 'assist', + icon: 'integrations/openreplay', + component: , + }, + { title: 'Zustand', slug: 'zustand', icon: '', header: '🐻', component: }, + ], + }, ]; diff --git a/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js b/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js index b17bbc460..906794155 100644 --- a/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js +++ b/frontend/app/components/Client/Integrations/JiraForm/JiraForm.js @@ -1,40 +1,45 @@ import React from 'react'; import IntegrationForm from '../IntegrationForm'; import DocLink from 'Shared/DocLink/DocLink'; +import { useModal } from 'App/components/Modal'; -const JiraForm = (props) => ( -
-

Jira

-
-
How to integrate Jira Cloud with OpenReplay.
-
- +const JiraForm = (props) => { + const { hideModal } = useModal(); + return ( +
+

Jira

+
+
How to integrate Jira Cloud with OpenReplay.
+
+ +
+
- -
-); + ) +}; JiraForm.displayName = 'JiraForm';