1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-04 00:18:01 +01:00

feat: limit component (#7538)

This commit is contained in:
Mateusz Kwasniewski 2024-07-04 09:49:31 +02:00 committed by GitHub
parent 30073d527a
commit c93bfafb7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 211 additions and 0 deletions

View File

@ -0,0 +1,67 @@
import { screen } from '@testing-library/react';
import { render } from 'utils/testRenderer';
import { Limit } from './Limit';
test('Render approaching limit variant', () => {
render(
<Limit
name='strategies in this environment'
shortName='strategies'
limit={10}
currentValue={8}
/>,
);
screen.getByText(
'You are nearing the limit for strategies in this environment',
);
screen.getByText('80%');
screen.getByText('Limit: 10');
});
test('Render reached limit variant', () => {
render(
<Limit
name='strategies in this environment'
shortName='strategies'
limit={10}
currentValue={10}
/>,
);
screen.getByText(
'You have reached the limit for strategies in this environment',
);
screen.getByText('100%');
screen.getByText('Limit: 10');
});
test('Render exceeded limit variant', () => {
render(
<Limit
name='strategies in this environment'
shortName='strategies'
limit={10}
currentValue={20}
/>,
);
screen.getByText(
'You have reached the limit for strategies in this environment',
);
screen.getByText('200%');
screen.getByText('Limit: 10');
});
test('Do not render any limit below threshold', () => {
render(
<Limit
name='strategies in this environment'
shortName='strategies'
limit={10}
currentValue={7}
/>,
);
expect(screen.queryByText('Limit: 10')).not.toBeInTheDocument();
});

View File

@ -0,0 +1,144 @@
import { Box, IconButton, styled, Tooltip, Typography } from '@mui/material';
import LinearProgress from '@mui/material/LinearProgress';
import { Link } from 'react-router-dom';
import WarningIcon from '@mui/icons-material/ErrorOutlined';
import ErrorIcon from '@mui/icons-material/Cancel';
import CloseIcon from '@mui/icons-material/Close';
import type { FC } from 'react';
import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender';
const StyledBox = styled(Box)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
border: `2px solid ${theme.palette.background.application}`,
borderRadius: `${theme.shape.borderRadiusMedium}px`,
}));
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
height: theme.spacing(1.5),
borderRadius: theme.shape.borderRadiusMedium,
}));
const StyledWarningIcon = styled(WarningIcon)(({ theme }) => ({
color: theme.palette.warning.border,
}));
const StyledErrorIcon = styled(ErrorIcon)(({ theme }) => ({
color: theme.palette.error.main,
}));
const Header = styled(Box)(({ theme }) => ({
display: 'flex',
gap: theme.spacing(1),
alignItems: 'center',
fontWeight: 'bold',
borderBottom: `2px solid ${theme.palette.background.application}`,
padding: theme.spacing(3, 4),
fontSize: theme.typography.h2.fontSize,
}));
const Footer = styled(Box)(({ theme }) => ({
padding: theme.spacing(3, 4),
}));
const Main = styled(Box)(({ theme }) => ({
borderBottom: `2px solid ${theme.palette.background.application}`,
padding: theme.spacing(3, 4),
}));
const LimitStats = styled(Box)(({ theme }) => ({
marginBottom: theme.spacing(2),
}));
const LimitExplanation = styled(Box)(({ theme }) => ({
display: 'flex',
justifyContent: 'space-between',
marginTop: theme.spacing(1.5),
}));
const ExpandableBox = styled(Box)(({ theme }) => ({
flex: 1,
}));
export const Limit: FC<{
name: string;
shortName?: string;
limit: number;
currentValue: number;
onClose?: () => void;
}> = ({ name, shortName, limit, currentValue, onClose }) => {
const percentageLimit = Math.round((currentValue / limit) * 100);
const belowLimit = currentValue < limit;
const threshold = 80;
if (percentageLimit < threshold) {
return null;
}
return (
<StyledBox>
<Header>
<ConditionallyRender
condition={belowLimit}
show={<StyledWarningIcon fontSize='large' />}
elseShow={<StyledErrorIcon fontSize='large' />}
/>
<ConditionallyRender
condition={belowLimit}
show={
<ExpandableBox>
You are nearing the limit for {name}
</ExpandableBox>
}
elseShow={
<ExpandableBox>
You have reached the limit for {name}
</ExpandableBox>
}
/>
<ConditionallyRender
condition={typeof onClose === 'function'}
show={
<Tooltip title='Close' arrow describeChild>
<IconButton onClick={onClose}>
<CloseIcon />
</IconButton>
</Tooltip>
}
/>
</Header>
<Main>
<LimitStats>
You have added {currentValue} {shortName ?? name}, which is
equivalent to{' '}
<Typography component='span' color='primary'>
{percentageLimit}%
</Typography>{' '}
of the limit.
</LimitStats>
<BorderLinearProgress
variant='determinate'
value={Math.min(100, percentageLimit)}
/>
<LimitExplanation>
<Link
target='_blank'
to={'https://docs.getunleash.io/reference/limits'}
>
Read more about limits
</Link>
<Typography fontWeight='bold'>Limit: {limit}</Typography>
</LimitExplanation>
</Main>
<Footer>
If you need more than <strong>{limit}</strong>{' '}
{shortName ?? name}, please reach out to us at{' '}
<a href='mailto:cs@getunleash.io?subject=Increase limit'>
cs@getunleash.io
</a>
</Footer>
</StyledBox>
);
};