mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
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>
 | 
						||
    );
 | 
						||
};
 |