-
-
Notifications
You must be signed in to change notification settings - Fork 730
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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:[email protected]?subject=Increase limit'> | ||
[email protected] | ||
</a> | ||
</Footer> | ||
</StyledBox> | ||
); | ||
}; |