Skip to content

Commit

Permalink
Integrations form (#4622)
Browse files Browse the repository at this point in the history
## About the changes
Redesigned/refactored integrations form.


![image](https://github.com/Unleash/unleash/assets/2625371/9f3ad019-e367-4f89-932d-539d7a370f88)

Closes
[1-1298/resesign-of-integrations-form](https://linear.app/unleash/issue/1-1298/resesign-of-integrations-form)
  • Loading branch information
Tymek committed Sep 7, 2023
1 parent fe51b50 commit e97859a
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 279 deletions.
Expand Up @@ -13,7 +13,6 @@ import { useInstanceStats } from '../../../../hooks/api/getters/useInstanceStats
import { formatApiPath } from '../../../../utils/formatPath';
import { PageContent } from '../../../common/PageContent/PageContent';
import { PageHeader } from '../../../common/PageHeader/PageHeader';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';

export const InstanceStats: VFC = () => {
const { stats } = useInstanceStats();
Expand Down
63 changes: 49 additions & 14 deletions frontend/src/component/common/FormTemplate/FormTemplate.tsx
Expand Up @@ -13,20 +13,21 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import Loader from '../Loader/Loader';
import copy from 'copy-to-clipboard';
import useToast from 'hooks/useToast';
import React, { useState } from 'react';
import React, { ReactNode, useState } from 'react';
import { ReactComponent as MobileGuidanceBG } from 'assets/img/mobileGuidanceBg.svg';
import { formTemplateSidebarWidth } from './FormTemplate.styles';
import { relative } from 'themes/themeStyles';

interface ICreateProps {
title?: string;
title?: ReactNode;
description: string;
documentationLink: string;
documentationLinkLabel: string;
loading?: boolean;
modal?: boolean;
disablePadding?: boolean;
formatApiCode?: () => string;
footer?: ReactNode;
}

const StyledContainer = styled('section', {
Expand All @@ -46,6 +47,17 @@ const StyledContainer = styled('section', {

const StyledRelativeDiv = styled('div')(({ theme }) => relative);

const StyledMain = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
flexShrink: 1,
width: '100%',
[theme.breakpoints.down(1100)]: {
width: '100%',
},
}));

const StyledFormContent = styled('div', {
shouldForwardProp: prop => prop !== 'disablePadding',
})<{ disablePadding?: boolean }>(({ theme, disablePadding }) => ({
Expand All @@ -65,6 +77,17 @@ const StyledFormContent = styled('div', {
},
}));

const StyledFooter = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(4, 6),
[theme.breakpoints.down('lg')]: {
padding: theme.spacing(4),
},
[theme.breakpoints.down(500)]: {
padding: theme.spacing(4, 2),
},
}));

const StyledTitle = styled('h1')(({ theme }) => ({
marginBottom: theme.fontSizes.mainHeader,
fontWeight: 'normal',
Expand Down Expand Up @@ -161,6 +184,7 @@ const FormTemplate: React.FC<ICreateProps> = ({
modal,
formatApiCode,
disablePadding,
footer,
}) => {
const { setToastData } = useToast();
const smallScreen = useMediaQuery(`(max-width:${1099}px)`);
Expand Down Expand Up @@ -219,21 +243,32 @@ const FormTemplate: React.FC<ICreateProps> = ({
</StyledRelativeDiv>
}
/>
<StyledFormContent disablePadding={disablePadding}>
<StyledMain>
<StyledFormContent disablePadding={disablePadding}>
<ConditionallyRender
condition={loading || false}
show={<Loader />}
elseShow={
<>
<ConditionallyRender
condition={title !== undefined}
show={<StyledTitle>{title}</StyledTitle>}
/>
{children}
</>
}
/>
</StyledFormContent>
<ConditionallyRender
condition={loading || false}
show={<Loader />}
elseShow={
condition={footer !== undefined}
show={() => (
<>
<ConditionallyRender
condition={title !== undefined}
show={<StyledTitle>{title}</StyledTitle>}
/>
{children}
<Divider />
<StyledFooter>{footer}</StyledFooter>
</>
}
/>{' '}
</StyledFormContent>
)}
/>
</StyledMain>
<ConditionallyRender
condition={!smallScreen}
show={
Expand Down
@@ -0,0 +1,76 @@
import { useState, type VFC } from 'react';
import { useNavigate } from 'react-router-dom';
import { styled } from '@mui/material';
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import type { AddonSchema } from 'openapi';
import useAddonsApi from 'hooks/api/actions/useAddonsApi/useAddonsApi';
import useAddons from 'hooks/api/getters/useAddons/useAddons';
import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { DELETE_ADDON } from 'component/providers/AccessProvider/permissions';
import { StyledHelpText, StyledTitle } from '../IntegrationForm.styles';

interface IIntegrationDeleteProps {
id: AddonSchema['id'];
}

const StyledContainer = styled('div')(({ theme }) => ({
margin: theme.spacing(1, 0, 6),
display: 'flex',
justifyContent: 'flex-end',
}));

export const IntegrationDelete: VFC<IIntegrationDeleteProps> = ({ id }) => {
const [isOpen, setIsOpen] = useState(false);
const { removeAddon } = useAddonsApi();
const { refetchAddons } = useAddons();
const { setToastData, setToastApiError } = useToast();
const navigate = useNavigate();
const onSubmit = async () => {
try {
await removeAddon(id);
refetchAddons();
setToastData({
type: 'success',
title: 'Success',
text: 'Deleted addon successfully',
});
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
}
navigate('/integrations');
};

return (
<>
<StyledTitle>Delete integration</StyledTitle>
<StyledHelpText>
Deleting an integration it will delete the entire configuration
and it will automatically disable the integration
</StyledHelpText>
<StyledContainer>
<PermissionButton
type="button"
variant="outlined"
color="error"
permission={DELETE_ADDON}
onClick={e => {
e.preventDefault();
setIsOpen(true);
}}
>
Delete integration
</PermissionButton>
</StyledContainer>
<Dialogue
open={isOpen}
onClick={onSubmit}
onClose={() => setIsOpen(false)}
title="Confirm deletion"
>
<div>Are you sure you want to delete this Addon?</div>
</Dialogue>
</>
);
};

This file was deleted.

@@ -1,58 +1,98 @@
import { styled } from '@mui/system';
import { FormControlLabel, TextField } from '@mui/material';
import { Paper, styled } from '@mui/material';
import { FormControlLabel, TextField, Typography } from '@mui/material';
import { forwardRef, type FC, type ReactNode, ComponentProps } from 'react';

export const StyledForm = styled('form')({
export const StyledForm = styled('form')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
height: '100%',
gap: '1rem',
});

export const StyledFormSection = styled('section')({
marginBottom: '36px',
});
gap: theme.spacing(2),
marginTop: theme.spacing(1),
}));

export const StyledAlerts = styled(StyledFormSection)(({ theme }) => ({
export const StyledAlerts = styled('section')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2),
}));

export const StyledHelpText = styled('p')({
marginBottom: '0.5rem',
});
export const StyledHelpText = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(1),
color: theme.palette.text.secondary,
fontSize: theme.typography.body2.fontSize,
}));

export const StyledContainer = styled('div')({
maxWidth: '600px',
});
export const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(4),
}));

export const StyledButtonContainer = styled('div')({
marginTop: 'auto',
display: 'flex',
justifyContent: 'flex-end',
});

export const StyledButtonSection = styled('section')(({ theme }) => ({
display: 'flex',
justifyContent: 'flex-end',
paddingTop: theme.spacing(2),
gap: theme.spacing(1),
gap: theme.spacing(2),
}));

export const StyledTextField = styled(TextField)({
export const StyledTextField = styled(TextField)(({ theme }) => ({
width: '100%',
marginBottom: '1rem',
marginTop: '0px',
});
}));

export const StyledSelectAllFormControlLabel = styled(FormControlLabel)({
paddingBottom: '16px',
});
export const StyledSelectAllFormControlLabel = styled(FormControlLabel)(
({ theme }) => ({
paddingBottom: theme.spacing(1),
})
);

export const StyledTitle = styled('h4')({
marginBottom: '8px',
});
export const StyledTitle = forwardRef<
HTMLHeadingElement,
{ children: ReactNode }
>(({ children }, ref) => (
<Typography
ref={ref}
component="h4"
variant="h4"
sx={theme => ({
margin: theme.spacing(1, 0),
})}
>
{children}
</Typography>
));

export const StyledAddonParameterContainer = styled('div')({
marginTop: '25px',
});

export const StyledConfigurationSection = styled('section')(({ theme }) => ({
borderWidth: '1px',
borderStyle: 'solid',
borderColor: theme.palette.neutral.border,
borderRadius: `${theme.shape.borderRadiusLarge}px`,
padding: theme.spacing(3),
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(3),
}));

export const StyledRaisedSection: FC<ComponentProps<typeof Paper>> = ({
...props
}) => (
<Paper
elevation={0}
sx={theme => ({
background: theme.palette.background.elevation1,
padding: theme.spacing(2, 3),
display: 'flex',
flexDirection: 'column',
width: '100%',
borderRadius: `${theme.shape.borderRadiusLarge}px`,
})}
{...props}
/>
);

0 comments on commit e97859a

Please sign in to comment.