From 586cdb09ab26bbfed32b8c3838fa4681d906a519 Mon Sep 17 00:00:00 2001 From: Jorge Padilla Date: Fri, 26 Jan 2024 12:21:25 -0500 Subject: [PATCH] feat(frontend): add external integrations (#3567) --- .../IntegrationIcon/Icons/Cypress.tsx | 19 ++++++++ .../components/IntegrationIcon/Icons/K6.tsx | 19 ++++++++ .../IntegrationIcon/Icons/Playwright.tsx | 36 ++++++++++++++ .../IntegrationIcon/IntegrationIcon.tsx | 35 ++++++++++++++ web/src/components/IntegrationIcon/index.ts | 2 + .../TriggerTypeModal/IntegrationTypeCard.tsx | 34 ++++++++++++++ .../TriggerTypeModal/TriggerTypeList.tsx | 47 +++++++++++++------ .../TriggerTypeModal.styled.ts | 17 +++++++ web/src/constants/Integrations.constants.ts | 43 +++++++++++++++++ 9 files changed, 238 insertions(+), 14 deletions(-) create mode 100644 web/src/components/IntegrationIcon/Icons/Cypress.tsx create mode 100644 web/src/components/IntegrationIcon/Icons/K6.tsx create mode 100644 web/src/components/IntegrationIcon/Icons/Playwright.tsx create mode 100644 web/src/components/IntegrationIcon/IntegrationIcon.tsx create mode 100644 web/src/components/IntegrationIcon/index.ts create mode 100644 web/src/components/TriggerTypeModal/IntegrationTypeCard.tsx create mode 100644 web/src/constants/Integrations.constants.ts diff --git a/web/src/components/IntegrationIcon/Icons/Cypress.tsx b/web/src/components/IntegrationIcon/Icons/Cypress.tsx new file mode 100644 index 0000000000..a409cf601a --- /dev/null +++ b/web/src/components/IntegrationIcon/Icons/Cypress.tsx @@ -0,0 +1,19 @@ +import {IIconProps} from '../IntegrationIcon'; + +const Cypress = ({color, width = '16', height = '16'}: IIconProps) => ( + + + + + + + + + + +); + +export default Cypress; diff --git a/web/src/components/IntegrationIcon/Icons/K6.tsx b/web/src/components/IntegrationIcon/Icons/K6.tsx new file mode 100644 index 0000000000..3540c8112b --- /dev/null +++ b/web/src/components/IntegrationIcon/Icons/K6.tsx @@ -0,0 +1,19 @@ +import {IIconProps} from '../IntegrationIcon'; + +const K6 = ({color, width = '16', height = '16'}: IIconProps) => ( + + + + + + + + + + +); + +export default K6; diff --git a/web/src/components/IntegrationIcon/Icons/Playwright.tsx b/web/src/components/IntegrationIcon/Icons/Playwright.tsx new file mode 100644 index 0000000000..7369905232 --- /dev/null +++ b/web/src/components/IntegrationIcon/Icons/Playwright.tsx @@ -0,0 +1,36 @@ +import {IIconProps} from '../IntegrationIcon'; + +const Playwright = ({color, width = '16', height = '16'}: IIconProps) => ( + + + + + + + + + +); + +export default Playwright; diff --git a/web/src/components/IntegrationIcon/IntegrationIcon.tsx b/web/src/components/IntegrationIcon/IntegrationIcon.tsx new file mode 100644 index 0000000000..ca3c5eefb9 --- /dev/null +++ b/web/src/components/IntegrationIcon/IntegrationIcon.tsx @@ -0,0 +1,35 @@ +import {useTheme} from 'styled-components'; +import {SupportedIntegrations} from 'constants/Integrations.constants'; +import Cypress from './Icons/Cypress'; +import K6 from './Icons/K6'; +import Playwright from './Icons/Playwright'; + +const iconMap = { + [SupportedIntegrations.CYPRESS]: Cypress, + [SupportedIntegrations.PLAYWRIGHT]: Playwright, + [SupportedIntegrations.K6]: K6, +} as const; + +interface IProps { + color?: string; + integrationName: SupportedIntegrations; + width?: string; + height?: string; +} + +export interface IIconProps { + color: string; + width?: string; + height?: string; +} + +const IntegrationIcon = ({color, integrationName, width, height}: IProps) => { + const { + color: {text: defaultColor}, + } = useTheme(); + const Component = iconMap[integrationName]; + + return ; +}; + +export default IntegrationIcon; diff --git a/web/src/components/IntegrationIcon/index.ts b/web/src/components/IntegrationIcon/index.ts new file mode 100644 index 0000000000..ca020ed5c5 --- /dev/null +++ b/web/src/components/IntegrationIcon/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-restricted-exports +export {default} from './IntegrationIcon'; diff --git a/web/src/components/TriggerTypeModal/IntegrationTypeCard.tsx b/web/src/components/TriggerTypeModal/IntegrationTypeCard.tsx new file mode 100644 index 0000000000..ce0b10011c --- /dev/null +++ b/web/src/components/TriggerTypeModal/IntegrationTypeCard.tsx @@ -0,0 +1,34 @@ +import IntegrationIcon from 'components/IntegrationIcon/'; +import {GITHUB_ISSUES_URL} from 'constants/Common.constants'; +import {IIntegration} from 'constants/Integrations.constants'; +import * as S from './TriggerTypeModal.styled'; + +interface IProps { + integration: IIntegration; +} + +const IntegrationTypeCard = ({integration: {name, title, isActive, isAvailable, url}}: IProps) => ( + + + + + +
+ + {title} {!isAvailable && '*'}{' '} + + {!isActive && ( + +  -{' '} + + Coming soon! + + + )} +
+ + + +); + +export default IntegrationTypeCard; diff --git a/web/src/components/TriggerTypeModal/TriggerTypeList.tsx b/web/src/components/TriggerTypeModal/TriggerTypeList.tsx index 50fb7d668c..14e446be65 100644 --- a/web/src/components/TriggerTypeModal/TriggerTypeList.tsx +++ b/web/src/components/TriggerTypeModal/TriggerTypeList.tsx @@ -1,12 +1,15 @@ import {useState} from 'react'; import CreateTestAnalytics from 'services/Analytics/CreateTest.service'; +import {Integrations} from 'constants/Integrations.constants'; import {CreateTriggerTypeToPlugin} from 'constants/Plugins.constants'; import {TriggerTypes} from 'constants/Test.constants'; import {withCustomization} from 'providers/Customization'; +import IntegrationTypeCard from './IntegrationTypeCard'; import TriggerTypeCard from './TriggerTypeCard'; import * as S from './TriggerTypeModal.styled'; const pluginList = Object.values(CreateTriggerTypeToPlugin); +const integrationList = Object.values(Integrations); interface IProps { onClick(plugin: TriggerTypes): void; @@ -16,20 +19,36 @@ const TriggerTypeList = ({onClick}: IProps) => { const [selectedType, setSelectedType] = useState(undefined); return ( - - {pluginList.map(plugin => ( - { - CreateTestAnalytics.onTriggerSelect(selectedPlugin.type); - onClick(selectedPlugin.type); - setSelectedType(selectedPlugin.type); - }} - plugin={plugin} - /> - ))} - + <> + + {pluginList.map(plugin => ( + { + CreateTestAnalytics.onTriggerSelect(selectedPlugin.type); + onClick(selectedPlugin.type); + setSelectedType(selectedPlugin.type); + }} + plugin={plugin} + /> + ))} + + + + + + Or trigger a Tracetest via an external integration + + + + {integrationList.map(integration => ( + + ))} + + + * this capability is limited to the commercial version of Tracetest. + ); }; diff --git a/web/src/components/TriggerTypeModal/TriggerTypeModal.styled.ts b/web/src/components/TriggerTypeModal/TriggerTypeModal.styled.ts index 65ef1ba2f7..4791773ee1 100644 --- a/web/src/components/TriggerTypeModal/TriggerTypeModal.styled.ts +++ b/web/src/components/TriggerTypeModal/TriggerTypeModal.styled.ts @@ -35,6 +35,11 @@ export const CardContainer = styled.div<{$isActive: boolean; $isSelected: boolea `} `; +export const IntegrationCardContainer = styled(CardContainer)` + width: auto; + padding-right: 16px; +`; + export const CardContent = styled.div` display: flex; flex-direction: column; @@ -52,6 +57,10 @@ export const CardList = styled.div` margin-bottom: 48px; `; +export const IntegrationCardList = styled(CardList)` + margin-bottom: 16px; +`; + export const CardTitle = styled(Typography.Text).attrs({ strong: true, })<{$isActive: boolean}>` @@ -97,3 +106,11 @@ export const Title = styled(Typography.Title)<{$marginBottom?: number}>` margin-bottom: ${({$marginBottom}) => $marginBottom || 0}px; } `; + +export const Text = styled(Typography.Text)``; + +export const Divider = styled.div` + height: 1px; + border-top: 1px dashed ${({theme}) => theme.color.borderLight}; + margin-bottom: 24px; +`; diff --git a/web/src/constants/Integrations.constants.ts b/web/src/constants/Integrations.constants.ts new file mode 100644 index 0000000000..515ef6cc89 --- /dev/null +++ b/web/src/constants/Integrations.constants.ts @@ -0,0 +1,43 @@ +export interface IIntegration { + name: SupportedIntegrations; + title: string; + url: string; + isActive: boolean; + isAvailable: boolean; +} + +export enum SupportedIntegrations { + CYPRESS = 'Cypress', + PLAYWRIGHT = 'Playwright', + K6 = 'K6', +} + +const Cypress: IIntegration = { + name: SupportedIntegrations.CYPRESS, + title: 'Cypress', + url: 'https://docs.tracetest.io/tools-and-integrations/cypress', + isActive: true, + isAvailable: false, +}; + +const K6: IIntegration = { + name: SupportedIntegrations.K6, + title: 'K6', + url: 'https://docs.tracetest.io/tools-and-integrations/k6', + isActive: true, + isAvailable: true, +}; + +const Playwright: IIntegration = { + name: SupportedIntegrations.PLAYWRIGHT, + title: 'Playwright', + url: 'https://docs.tracetest.io/tools-and-integrations/playwright', + isActive: true, + isAvailable: false, +}; + +export const Integrations = { + [SupportedIntegrations.CYPRESS]: Cypress, + [SupportedIntegrations.PLAYWRIGHT]: Playwright, + [SupportedIntegrations.K6]: K6, +} as const;