1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-27 11:02:16 +01:00
unleash.unleash/frontend/src/component/layout/MainLayout/DraftBanner/DraftBanner.tsx
2024-05-27 13:35:27 +02:00

172 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { type FC, Fragment, useMemo, useState, type VFC } from 'react';
import { Box, Button, styled, Typography } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { ChangeRequestSidebar } from 'component/changeRequest/ChangeRequestSidebar/ChangeRequestSidebar';
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
import type { ChangeRequestType } from 'component/changeRequest/changeRequest.types';
import { changesCount } from 'component/changeRequest/changesCount';
import { Sticky } from 'component/common/Sticky/Sticky';
import { useUiFlag } from 'hooks/useUiFlag';
interface IDraftBannerProps {
project: string;
}
const StyledDraftBannerContentWrapper = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: theme.spacing(1, 0),
}));
const OldStyledDraftBanner = styled(Box)(({ theme }) => ({
maxWidth: '1512px',
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
marginLeft: 'auto',
marginRight: 'auto',
[theme.breakpoints.down(1024)]: {
width: '100%',
marginLeft: 0,
marginRight: 0,
},
[theme.breakpoints.down('sm')]: {
minWidth: '100%',
},
}));
const StyledDraftBanner = styled(Box)(({ theme }) => ({
width: '100%',
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(9),
marginLeft: 'auto',
marginRight: 'auto',
[theme.breakpoints.down('lg')]: {
marginLeft: 0,
marginRight: 0,
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
},
[theme.breakpoints.down('sm')]: {
minWidth: '100%',
},
}));
const DraftBannerContent: FC<{
changeRequests: ChangeRequestType[];
onClick: () => void;
}> = ({ changeRequests, onClick }) => {
const sidebarNavigationEnabled = useUiFlag('navigationSidebar');
const environments = changeRequests.map(({ environment }) => environment);
const allChangesCount = changeRequests.reduce(
(acc, curr) => acc + changesCount(curr),
0,
);
const showOneLongExplanation =
changeRequests.length === 1 &&
['Draft', 'In review', 'Approved'].includes(changeRequests[0].state);
const explanation = showOneLongExplanation
? {
Draft: ' that need to be reviewed',
'In review': ' that are in review',
Approved:
' that are approved. Adding more changes will clear the approvals and require a new review',
}[changeRequests[0].state as 'Draft' | 'In review' | 'Approved']
: '';
const Banner = sidebarNavigationEnabled
? StyledDraftBanner
: OldStyledDraftBanner;
return (
<Banner>
<StyledDraftBannerContentWrapper>
<Typography variant='body2' sx={{ mr: 4 }}>
<strong>Change request mode</strong> You have changes{' '}
<ConditionallyRender
condition={Boolean(environments)}
show={
<>
in{' '}
{environments.map((env, i) =>
i === 0 ? (
<Fragment key={env}>
<strong>{env}</strong>
</Fragment>
) : (
<Fragment key={env}>
{i === environments.length - 1
? ' and '
: ', '}
<strong>{env}</strong>
</Fragment>
),
)}
</>
}
/>
{explanation}.
</Typography>
<Button
variant='contained'
onClick={onClick}
sx={{ ml: 'auto' }}
>
View changes ({allChangesCount})
</Button>
</StyledDraftBannerContentWrapper>
</Banner>
);
};
const StickyBanner = styled(Sticky)(({ theme }) => ({
borderTop: `1px solid ${theme.palette.warning.border}`,
borderBottom: `1px solid ${theme.palette.warning.border}`,
color: theme.palette.warning.contrastText,
backgroundColor: theme.palette.warning.light,
zIndex: 250,
}));
export const DraftBanner: VFC<IDraftBannerProps> = ({ project }) => {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const { data, loading } = usePendingChangeRequests(project);
const unfinishedChangeRequests = useMemo(
() =>
data?.filter((changeRequest) =>
['Draft', 'In review', 'Approved'].includes(
changeRequest.state,
),
),
[data],
);
if ((!loading && !data) || data?.length === 0) {
return null;
}
return (
<StickyBanner>
<ConditionallyRender
condition={Boolean(unfinishedChangeRequests?.length)}
show={
<DraftBannerContent
changeRequests={
unfinishedChangeRequests as ChangeRequestType[]
}
onClick={() => {
setIsSidebarOpen(true);
}}
/>
}
/>
<ChangeRequestSidebar
project={project}
open={isSidebarOpen}
onClose={() => {
setIsSidebarOpen(false);
}}
/>
</StickyBanner>
);
};