Skip to content

Commit

Permalink
feat: jira plugin page (#4627)
Browse files Browse the repository at this point in the history
  • Loading branch information
sjaanus authored Sep 7, 2023
1 parent 3b754ec commit 1d414db
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 29 deletions.
1 change: 1 addition & 0 deletions frontend/src/assets/icons/jira-comment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 15 additions & 1 deletion frontend/src/assets/icons/jira.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/img/jira/connect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/img/jira/cr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/img/jira/manage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 39 additions & 27 deletions frontend/src/component/common/FormTemplate/FormTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface ICreateProps {
loading?: boolean;
modal?: boolean;
disablePadding?: boolean;
formatApiCode: () => string;
formatApiCode?: () => string;
}

const StyledContainer = styled('section', {
Expand Down Expand Up @@ -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!()} />{' '}
</>
);
}
};

Expand Down Expand Up @@ -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>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -34,7 +35,7 @@ export const IntegrationIcon = ({ name }: IIntegrationIconProps) => {
<img
style={style}
alt="JIRA logo"
src={formatAssetPath(jiraIcon)}
src={formatAssetPath(jiraCommentIcon)}
/>
);
case 'webhook':
Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
);
};
Original file line number Diff line number Diff line change
@@ -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. You’ll receive a link inside Jira to review, approve, and apply the change.'
}
src={cr}
/>
</StyledContainer>
</FormTemplate>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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": {},
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/component/menu/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand Down

0 comments on commit 1d414db

Please sign in to comment.