1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-18 11:14:57 +02:00
unleash.unleash/frontend/src/component/project/Project/ProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx
Tymoteusz Czech dbd897e3bd
Feat/new paginated table (#5371)
## About the changes
2023-11-24 17:50:58 +01:00

210 lines
7.5 KiB
TypeScript

import { useEffect, useState, VFC } from 'react';
import {
IconButton,
ListItemIcon,
ListItemText,
MenuList,
Popover,
Tooltip,
Typography,
useMediaQuery,
useTheme,
} from '@mui/material';
import ColumnIcon from '@mui/icons-material/ViewWeek';
import CloseIcon from '@mui/icons-material/Close';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import {
StyledBoxContainer,
StyledBoxMenuHeader,
StyledCheckbox,
StyledDivider,
StyledIconButton,
StyledMenuItem,
} from './ColumnsMenu.styles';
interface IColumnsMenuProps {
allColumns: {
Header?: string | any;
id: string;
isVisible: boolean;
toggleHidden: (state: boolean) => void;
hideInMenu?: boolean;
}[];
staticColumns?: string[];
dividerBefore?: string[];
dividerAfter?: string[];
isCustomized?: boolean;
setHiddenColumns: (hiddenColumns: string[]) => void;
onCustomize?: () => void;
}
const columnNameMap: Record<string, string> = {
favorite: 'Favorite',
};
export const ColumnsMenu: VFC<IColumnsMenuProps> = ({
allColumns,
staticColumns = [],
dividerBefore = [],
dividerAfter = [],
isCustomized = false,
onCustomize,
setHiddenColumns,
}) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const theme = useTheme();
const isTinyScreen = useMediaQuery(theme.breakpoints.down('sm'));
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
useEffect(() => {
if (isCustomized) {
return;
}
const setVisibleColumns = (
columns: string[],
environmentsToShow: number = 0,
) => {
const visibleEnvColumns = allColumns
.filter(({ id }) => id.startsWith('environment:') !== false)
.map(({ id }) => id)
.slice(0, environmentsToShow);
const hiddenColumns = allColumns
.map(({ id }) => id)
.filter((id) => !columns.includes(id))
.filter((id) => !staticColumns.includes(id))
.filter((id) => !visibleEnvColumns.includes(id));
setHiddenColumns(hiddenColumns);
};
if (isTinyScreen) {
return setVisibleColumns(['createdAt']);
}
if (isSmallScreen) {
return setVisibleColumns(['createdAt'], 1);
}
if (isMediumScreen) {
return setVisibleColumns(['type', 'createdAt'], 1);
}
setVisibleColumns(['lastSeenAt', 'type', 'createdAt'], 3);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isTinyScreen, isSmallScreen, isMediumScreen]);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const isOpen = Boolean(anchorEl);
const id = `columns-menu`;
const menuId = `columns-menu-list-${id}`;
return (
<StyledBoxContainer>
<Tooltip title='Select columns' arrow describeChild>
<StyledIconButton
id={id}
aria-controls={isOpen ? menuId : undefined}
aria-haspopup='true'
aria-expanded={isOpen ? 'true' : undefined}
onClick={handleClick}
type='button'
size='large'
data-loading
>
<ColumnIcon />
</StyledIconButton>
</Tooltip>
<Popover
id={menuId}
open={isOpen}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
disableScrollLock={true}
PaperProps={{
sx: (theme) => ({
borderRadius: theme.shape.borderRadius,
paddingBottom: theme.spacing(2),
}),
}}
>
<StyledBoxMenuHeader>
<Typography variant='body2'>
<strong>Columns</strong>
</Typography>
<IconButton onClick={handleClose}>
<CloseIcon />
</IconButton>
</StyledBoxMenuHeader>
<MenuList>
{allColumns
.filter(({ hideInMenu }) => !hideInMenu)
.map((column) => [
<ConditionallyRender
condition={dividerBefore.includes(column.id)}
show={<StyledDivider />}
/>,
<StyledMenuItem
onClick={() => {
column.toggleHidden(column.isVisible);
onCustomize?.();
}}
disabled={staticColumns.includes(column.id)}
>
<ListItemIcon>
<StyledCheckbox
edge='start'
checked={column.isVisible}
disableRipple
inputProps={{
'aria-labelledby': column.id,
}}
size='medium'
/>
</ListItemIcon>
<ListItemText
id={column.id}
primary={
<Typography variant='body2'>
<ConditionallyRender
condition={Boolean(
typeof column.Header ===
'string' &&
column.Header,
)}
show={() => (
<>{column.Header}</>
)}
elseShow={() =>
columnNameMap[column.id] ||
column.id
}
/>
</Typography>
}
/>
</StyledMenuItem>,
<ConditionallyRender
condition={dividerAfter.includes(column.id)}
show={<StyledDivider />}
/>,
])}
</MenuList>
</Popover>
</StyledBoxContainer>
);
};