From 8a5a73ad7d4a90f9cea7e52f9bd85ec50f4bb573 Mon Sep 17 00:00:00 2001 From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:41:25 +0100 Subject: [PATCH] feat: new columns visibility menu (#5604) New `` is using it's own list of elements instead of inferring it from table columns definition. This component doesn't need it's internal structure to depend on react-table and it's interface. --- .../ExperimentalColumnsMenu.styles.ts | 41 ++++++ .../ExperimentalColumnsMenu.tsx | 134 ++++++++++++++++++ .../ExperimentalProjectTable.tsx | 27 +++- .../ProjectFeatureTogglesHeader.tsx | 15 +- 4 files changed, 205 insertions(+), 12 deletions(-) create mode 100644 frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts create mode 100644 frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx diff --git a/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts new file mode 100644 index 0000000000..c688a3def3 --- /dev/null +++ b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts @@ -0,0 +1,41 @@ +import { + Box, + Checkbox, + Divider, + IconButton, + MenuItem, + styled, +} from '@mui/material'; + +import { flexRow } from 'themes/themeStyles'; + +export const StyledBoxContainer = styled(Box)(() => ({ + ...flexRow, + justifyContent: 'center', +})); + +export const StyledIconButton = styled(IconButton)(({ theme }) => ({ + margin: theme.spacing(-1, 0), +})); + +export const StyledBoxMenuHeader = styled(Box)(({ theme }) => ({ + ...flexRow, + justifyContent: 'space-between', + padding: theme.spacing(1, 1, 0, 4), +})); + +export const StyledMenuItem = styled(MenuItem)(({ theme }) => ({ + padding: theme.spacing(0, 2), + margin: theme.spacing(0, 2), + borderRadius: theme.shape.borderRadius, +})); + +export const StyledDivider = styled(Divider)(({ theme }) => ({ + '&.MuiDivider-root.MuiDivider-fullWidth': { + margin: theme.spacing(0.75, 0), + }, +})); + +export const StyledCheckbox = styled(Checkbox)(({ theme }) => ({ + padding: theme.spacing(0.75, 1), +})); diff --git a/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx new file mode 100644 index 0000000000..f5cc8acad4 --- /dev/null +++ b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx @@ -0,0 +1,134 @@ +import { useEffect, useState, VFC } from 'react'; +import { + IconButton, + ListItemIcon, + ListItemText, + MenuList, + Popover, + Tooltip, + Typography, +} from '@mui/material'; +import ColumnIcon from '@mui/icons-material/ViewWeek'; +import CloseIcon from '@mui/icons-material/Close'; +import { + StyledBoxContainer, + StyledBoxMenuHeader, + StyledCheckbox, + StyledDivider, + StyledIconButton, + StyledMenuItem, +} from './ExperimentalColumnsMenu.styles'; + +interface IColumnsMenuProps { + columns: { + header?: string; + id: string; + isStatic?: boolean; + isVisible?: boolean; + }[]; + onToggle?: (id: string) => void; +} + +export const ExperimentalColumnsMenu: VFC = ({ + columns, + onToggle, +}) => { + const [anchorEl, setAnchorEl] = useState(null); + + const onIconClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const isOpen = Boolean(anchorEl); + const id = `columns-menu`; + const menuId = `columns-menu-list-${id}`; + + return ( + + + + + + + + ({ + borderRadius: theme.shape.borderRadius, + paddingBottom: theme.spacing(2), + }), + }} + > + + + Columns + + + + + + + {columns.map((column) => + column.id === 'divider' ? ( + + ) : ( + { + onToggle?.(column.id); + }} + disabled={column.isStatic === true} + > + + + + + {column.header} + + } + /> + + ), + )} + + + + ); +}; diff --git a/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalProjectTable.tsx b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalProjectTable.tsx index 35c43e0ab5..f103fb6c07 100644 --- a/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalProjectTable.tsx +++ b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ExperimentalProjectTable.tsx @@ -50,7 +50,7 @@ import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/Fa import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell'; import { ProjectEnvironmentType } from '../../ProjectFeatureToggles/hooks/useEnvironmentsRef'; import { ActionsCell } from '../../ProjectFeatureToggles/ActionsCell/ActionsCell'; -import { ColumnsMenu } from '../../ProjectFeatureToggles/ColumnsMenu/ColumnsMenu'; +import { ExperimentalColumnsMenu as ColumnsMenu } from './ExperimentalColumnsMenu/ExperimentalColumnsMenu'; import { useStyles } from '../../ProjectFeatureToggles/ProjectFeatureToggles.styles'; import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi'; import { FeatureTagCell } from 'component/common/Table/cells/FeatureTagCell/FeatureTagCell'; @@ -333,6 +333,31 @@ export const ExperimentalProjectFeatureToggles = ({ environmentsToExport={environments.map( ({ environment }) => environment, )} + actions={ + + } /> } > diff --git a/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx index 03d3343863..7dcb8f3d7c 100644 --- a/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx +++ b/frontend/src/component/project/Project/ExperimentalProjectFeatures/ExperimentalProjectTable/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx @@ -1,4 +1,4 @@ -import { VFC, useState } from 'react'; +import { ReactNode, VFC, useState } from 'react'; import { Box, IconButton, @@ -28,6 +28,7 @@ interface IProjectFeatureTogglesHeaderProps { onChangeSearchQuery?: (query: string) => void; dataToExport?: Pick[]; environmentsToExport?: string[]; + actions?: ReactNode; } const StyledResponsiveButton = styled(ResponsiveButton)(() => ({ @@ -43,6 +44,7 @@ export const ProjectFeatureTogglesHeader: VFC< onChangeSearchQuery, dataToExport, environmentsToExport, + actions, }) => { const projectId = useRequiredPathParam('projectId'); const headerLoadingRef = useLoading(isLoading || false); @@ -91,16 +93,7 @@ export const ProjectFeatureTogglesHeader: VFC< /> } /> - {/* FIXME: columns menu */} - {/* setIsCustomColumns(true)} - /> */} + {actions}