1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00
Jaanus Sellin 2023-09-07 11:51:50 +03:00 committed by GitHub
parent 3b754ec7ed
commit 1d414db982
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 255 additions and 29 deletions

View File

@ -0,0 +1 @@
<svg height="2500" preserveAspectRatio="xMidYMid" width="2500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 -30.632388516510233 255.324 285.95638851651023"><linearGradient id="a"><stop offset=".18" stop-color="#0052cc"/><stop offset="1" stop-color="#2684ff"/></linearGradient><linearGradient id="b" x1="98.031%" x2="58.888%" xlink:href="#a" y1=".161%" y2="40.766%"/><linearGradient id="c" x1="100.665%" x2="55.402%" xlink:href="#a" y1=".455%" y2="44.727%"/><path d="M244.658 0H121.707a55.502 55.502 0 0 0 55.502 55.502h22.649V77.37c.02 30.625 24.841 55.447 55.466 55.467V10.666C255.324 4.777 250.55 0 244.658 0z" fill="#2684ff"/><path d="M183.822 61.262H60.872c.019 30.625 24.84 55.447 55.466 55.467h22.649v21.938c.039 30.625 24.877 55.43 55.502 55.43V71.93c0-5.891-4.776-10.667-10.667-10.667z" fill="url(#b)"/><path d="M122.951 122.489H0c0 30.653 24.85 55.502 55.502 55.502h22.72v21.867c.02 30.597 24.798 55.408 55.396 55.466V133.156c0-5.891-4.776-10.667-10.667-10.667z" fill="url(#c)"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1 +1,15 @@
<svg height="2500" preserveAspectRatio="xMidYMid" width="2500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 -30.632388516510233 255.324 285.95638851651023"><linearGradient id="a"><stop offset=".18" stop-color="#0052cc"/><stop offset="1" stop-color="#2684ff"/></linearGradient><linearGradient id="b" x1="98.031%" x2="58.888%" xlink:href="#a" y1=".161%" y2="40.766%"/><linearGradient id="c" x1="100.665%" x2="55.402%" xlink:href="#a" y1=".455%" y2="44.727%"/><path d="M244.658 0H121.707a55.502 55.502 0 0 0 55.502 55.502h22.649V77.37c.02 30.625 24.841 55.447 55.466 55.467V10.666C255.324 4.777 250.55 0 244.658 0z" fill="#2684ff"/><path d="M183.822 61.262H60.872c.019 30.625 24.84 55.447 55.466 55.467h22.649v21.938c.039 30.625 24.877 55.43 55.502 55.43V71.93c0-5.891-4.776-10.667-10.667-10.667z" fill="url(#b)"/><path d="M122.951 122.489H0c0 30.653 24.85 55.502 55.502 55.502h22.72v21.867c.02 30.597 24.798 55.408 55.396 55.466V133.156c0-5.891-4.776-10.667-10.667-10.667z" fill="url(#c)"/></svg>
<svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M31.2987 15.1469L17.9562 1.58157L16.6466 0.25L6.61925 10.4448L2.03534 15.1469C1.54421 15.6464 1.54421 16.4369 2.03534 16.8947L11.2032 26.2157L16.6466 31.75L26.6738 21.5552L26.8375 21.3887L31.2987 16.8947C31.7898 16.3952 31.7898 15.6048 31.2987 15.1469ZM16.6466 20.6813L12.0626 16.0208L16.6466 11.3603L21.2305 16.0208L16.6466 20.6813Z" fill="#2684FF"/>
<path d="M16.6465 11.3451C13.6587 8.31147 13.6178 3.36621 16.6055 0.291016L6.61914 10.4724L12.0625 15.9995L16.6465 11.3451Z" fill="url(#paint0_linear_17148_2032)"/>
<path d="M21.2714 15.959L16.6465 20.6549C19.6752 23.73 19.6752 28.6752 16.6465 31.7505L26.7148 21.5276L21.2714 15.959Z" fill="url(#paint1_linear_17148_2032)"/>
<defs>
<linearGradient id="paint0_linear_17148_2032" x1="15.8439" y1="6.62639" x2="9.34422" y2="13.0277" gradientUnits="userSpaceOnUse">
<stop offset="0.176" stop-color="#0052CC"/>
<stop offset="1" stop-color="#2684FF"/>
</linearGradient>
<linearGradient id="paint1_linear_17148_2032" x1="17.5385" y1="25.3007" x2="24.0253" y2="18.9121" gradientUnits="userSpaceOnUse">
<stop offset="0.176" stop-color="#0052CC"/>
<stop offset="1" stop-color="#2684FF"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

View File

@ -26,7 +26,7 @@ interface ICreateProps {
loading?: boolean;
modal?: boolean;
disablePadding?: boolean;
formatApiCode: () => string;
formatApiCode?: () => string;
}
const StyledContainer = styled('section', {
@ -165,22 +165,43 @@ const FormTemplate: React.FC<ICreateProps> = ({
const { setToastData } = useToast();
const smallScreen = useMediaQuery(`(max-width:${1099}px)`);
const copyCommand = () => {
if (copy(formatApiCode())) {
setToastData({
title: 'Successfully copied the command',
text: 'The command should now be automatically copied to your clipboard',
autoHideDuration: 6000,
type: 'success',
show: true,
});
} else {
setToastData({
title: 'Could not copy the command',
text: 'Sorry, but we could not copy the command.',
autoHideDuration: 6000,
type: 'error',
show: true,
});
if (formatApiCode !== undefined) {
if (copy(formatApiCode())) {
setToastData({
title: 'Successfully copied the command',
text: 'The command should now be automatically copied to your clipboard',
autoHideDuration: 6000,
type: 'success',
show: true,
});
} else {
setToastData({
title: 'Could not copy the command',
text: 'Sorry, but we could not copy the command.',
autoHideDuration: 6000,
type: 'error',
show: true,
});
}
}
};
const renderApiInfo = (apiDisabled: boolean) => {
if (!apiDisabled) {
return (
<>
<StyledSidebarDivider />
<StyledSubtitle>
API Command{' '}
<Tooltip title="Copy command" arrow>
<IconButton onClick={copyCommand} size="large">
<StyledIcon />
</IconButton>
</Tooltip>
</StyledSubtitle>
<Codebox text={formatApiCode!()} />{' '}
</>
);
}
};
@ -221,16 +242,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
documentationLink={documentationLink}
documentationLinkLabel={documentationLinkLabel}
>
<StyledSidebarDivider />
<StyledSubtitle>
API Command{' '}
<Tooltip title="Copy command" arrow>
<IconButton onClick={copyCommand} size="large">
<StyledIcon />
</IconButton>
</Tooltip>
</StyledSubtitle>
<Codebox text={formatApiCode()} />
{renderApiInfo(formatApiCode === undefined)}
</Guidance>
}
/>

View File

@ -5,15 +5,19 @@ import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { IntegrationCard } from '../IntegrationCard/IntegrationCard';
import { StyledCardsGrid } from '../IntegrationList.styles';
import { JIRA_INFO } from '../../JiraIntegration/JiraIntegration';
interface IAvailableIntegrationsProps {
providers: AddonTypeSchema[];
loading?: boolean;
}
export const AvailableIntegrations: VFC<IAvailableIntegrationsProps> = ({
providers,
loading,
}) => {
const customProviders = [JIRA_INFO];
const ref = useLoading(loading || false);
return (
<PageContent
@ -30,6 +34,16 @@ export const AvailableIntegrations: VFC<IAvailableIntegrationsProps> = ({
link={`/integrations/create/${name}`}
/>
))}
{customProviders?.map(({ name, displayName, description }) => (
<IntegrationCard
key={name}
icon={name}
title={displayName || name}
description={description}
link={`/integrations/view/${name}`}
configureActionText={'View integration'}
/>
))}
</StyledCardsGrid>
</PageContent>
);

View File

@ -3,6 +3,7 @@ import { DeviceHub } from '@mui/icons-material';
import { formatAssetPath } from 'utils/formatPath';
import slackIcon from 'assets/icons/slack.svg';
import jiraCommentIcon from 'assets/icons/jira-comment.svg';
import jiraIcon from 'assets/icons/jira.svg';
import webhooksIcon from 'assets/icons/webhooks.svg';
import teamsIcon from 'assets/icons/teams.svg';
@ -34,7 +35,7 @@ export const IntegrationIcon = ({ name }: IIntegrationIconProps) => {
<img
style={style}
alt="JIRA logo"
src={formatAssetPath(jiraIcon)}
src={formatAssetPath(jiraCommentIcon)}
/>
);
case 'webhook':
@ -61,6 +62,14 @@ export const IntegrationIcon = ({ name }: IIntegrationIconProps) => {
src={formatAssetPath(dataDogIcon)}
/>
);
case 'jira':
return (
<img
style={style}
alt="JIRA logo"
src={formatAssetPath(jiraIcon)}
/>
);
default:
return (
<Avatar>

View File

@ -0,0 +1,45 @@
import { styled, Typography } from '@mui/material';
import { formatAssetPath } from '../../../utils/formatPath';
import { FC } from 'react';
export const StyledFigure = styled('figure')(({ theme }) => ({
display: 'flex',
gap: theme.spacing(2),
flexDirection: 'column',
}));
export const StyledFigCaption = styled('figcaption')(({ theme }) => ({
display: 'flex',
gap: theme.spacing(2),
flexDirection: 'column',
}));
export const StyledImg = styled('img')({
maxWidth: '100%',
maxHeight: '100%',
width: 'auto',
height: 'auto',
});
interface JiraIntegrationProps {
title: string;
description: string;
src: string;
}
export const JiraImageContainer: FC<JiraIntegrationProps> = ({
title,
description,
src,
}) => {
return (
<StyledFigure>
<StyledFigCaption>
<Typography variant={'h3'}>{title}</Typography>
<Typography>{description}</Typography>
</StyledFigCaption>
<StyledImg src={formatAssetPath(src)} alt={title} />
</StyledFigure>
);
};

View File

@ -0,0 +1,114 @@
import FormTemplate from '../../common/FormTemplate/FormTemplate';
import { Divider, styled } from '@mui/material';
import { IntegrationIcon } from '../IntegrationList/IntegrationIcon/IntegrationIcon';
import cr from 'assets/img/jira/cr.png';
import connect from 'assets/img/jira/connect.png';
import manage from 'assets/img/jira/manage.png';
import React from 'react';
import { JiraImageContainer } from './JiraImageContainer';
export const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2),
}));
export const StyledGrayContainer = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.grey[100],
borderRadius: theme.shape.borderRadiusLarge,
padding: theme.spacing(3),
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
}));
export const StyledIconLine = styled('div')(({ theme }) => ({
display: 'flex',
marginLeft: theme.spacing(1),
alignItems: 'center',
}));
export const StyledLink = styled('a')({
textDecoration: 'none',
});
export const JIRA_INFO = {
name: 'jira',
displayName: 'Jira',
description:
'Create, connect, manage, and approve Unleash feature flags directly from Jira',
documentationUrl:
'https://docs.getunleash.io/reference/integrations/jira-cloud-plugin-installation',
};
export const JiraIntegration = () => {
const { name, displayName, description, documentationUrl } = JIRA_INFO;
return (
<FormTemplate
title={`${displayName}`}
description={description || ''}
documentationLink={documentationUrl}
documentationLinkLabel="Jira documentation"
>
<StyledContainer>
<StyledGrayContainer>
<StyledIconLine>
<IntegrationIcon name={name} /> How does it work?
</StyledIconLine>
<ul>
<li>
Create a new feature flag directly within Jira, or
connect existing flags to any Jira issue.
</li>
<li>
Keep track of your flag status for each environment.
</li>
<li>
Activate/deactivate feature flags directly within
Jira.
</li>
<li>
Initiate change requests when guarded flags are
activated/deactivated within Jira.
</li>
</ul>
</StyledGrayContainer>
<StyledGrayContainer>
<StyledLink
target="_blank"
rel="noopener noreferrer"
href="https://marketplace.atlassian.com/apps/1231447/unleash-enterprise-for-jira"
>
View plugin on Atlassian marketplace
</StyledLink>
</StyledGrayContainer>
<Divider />
<JiraImageContainer
title={'Manage your feature flags for each environment'}
description={
'View your feature flag status for each of your environments. Quickly turn features on and off directly within Jira.'
}
src={manage}
/>
<Divider />
<JiraImageContainer
title={'Connect your feature flags to any Jira issue'}
description={
'Link as many feature flags as you want to any issue. Create new feature flags directly within Jira.'
}
src={connect}
/>
<Divider />
<JiraImageContainer
title={'Automatically initiate change requests'}
description={
'Automatically initiate change requests when you activate a guarded flag. Youll receive a link inside Jira to review, approve, and apply the change.'
}
src={cr}
/>
</StyledContainer>
</FormTemplate>
);
};

View File

@ -324,6 +324,14 @@ exports[`returns all baseRoutes 1`] = `
"title": "Create",
"type": "protected",
},
{
"component": [Function],
"menu": {},
"parent": "/integrations",
"path": "/integrations/view/:providerId",
"title": "View",
"type": "protected",
},
{
"component": [Function],
"menu": {},

View File

@ -45,6 +45,7 @@ import { LoginHistory } from 'component/loginHistory/LoginHistory';
import { FeatureTypesList } from 'component/featureTypes/FeatureTypesList';
import { AddonsList } from 'component/integrations/IntegrationList/AddonsList';
import { TemporaryApplicationListWrapper } from 'component/application/ApplicationList/TemporaryApplicationListWrapper';
import { JiraIntegration } from '../integrations/JiraIntegration/JiraIntegration';
export const routes: IRoute[] = [
// Splash
@ -337,6 +338,14 @@ export const routes: IRoute[] = [
type: 'protected',
menu: {},
},
{
path: '/integrations/view/:providerId',
parent: '/integrations',
title: 'View',
component: JiraIntegration,
type: 'protected',
menu: {},
},
{
path: '/integrations/edit/:addonId',
parent: '/integrations',