feat: show/hide table columns (#1078)

Closes #813
This commit is contained in:
Thaïs
2023-08-04 19:44:46 +02:00
committed by GitHub
parent 417ca3d131
commit c6bec40c90
20 changed files with 434 additions and 147 deletions

View File

@ -1,9 +1,8 @@
import React, { ComponentProps, useRef } from 'react';
import { cloneElement, ComponentProps, useRef } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconButton } from '@/ui/button/components/IconButton';
import { IconButtonGroup } from '@/ui/button/components/IconButtonGroup';
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
@ -19,23 +18,6 @@ const StyledColumnMenu = styled(DropdownMenu)`
font-weight: ${({ theme }) => theme.font.weight.regular};
`;
const StyledIconButtonGroup = styled(IconButtonGroup)`
display: none;
position: absolute;
right: ${({ theme }) => theme.spacing(1)};
`;
const styledIconButtonGroupClassName = 'column-menu-item-icon-button-group';
const StyledColumnMenuItem = styled(DropdownMenuItem)`
position: relative;
&:hover {
.${styledIconButtonGroupClassName} {
display: flex;
}
}
`;
type EntityTableColumnMenuProps = {
onAddViewField: (
viewFieldDefinition: ViewFieldDefinition<ViewFieldMetadata>,
@ -62,23 +44,21 @@ export const EntityTableColumnMenu = ({
<StyledColumnMenu {...props} ref={ref}>
<DropdownMenuItemsContainer>
{viewFieldDefinitions.map((viewFieldDefinition) => (
<StyledColumnMenuItem key={viewFieldDefinition.id}>
{viewFieldDefinition.columnIcon &&
React.cloneElement(viewFieldDefinition.columnIcon, {
size: theme.icon.size.md,
})}
{viewFieldDefinition.columnLabel}
<StyledIconButtonGroup
className={styledIconButtonGroupClassName}
variant="transparent"
size="small"
>
<DropdownMenuItem
key={viewFieldDefinition.id}
actions={
<IconButton
icon={<IconPlus size={theme.icon.size.sm} />}
onClick={() => onAddViewField(viewFieldDefinition)}
/>
</StyledIconButtonGroup>
</StyledColumnMenuItem>
}
>
{viewFieldDefinition.columnIcon &&
cloneElement(viewFieldDefinition.columnIcon, {
size: theme.icon.size.md,
})}
{viewFieldDefinition.columnLabel}
</DropdownMenuItem>
))}
</DropdownMenuItemsContainer>
</StyledColumnMenu>

View File

@ -19,6 +19,7 @@ import {
addableViewFieldDefinitionsState,
columnWidthByViewFieldIdState,
viewFieldsState,
visibleViewFieldsState,
} from '../states/viewFieldsState';
import type {
ViewFieldDefinition,
@ -87,8 +88,8 @@ const StyledEntityTableColumnMenu = styled(EntityTableColumnMenu)`
export function EntityTableHeader() {
const theme = useTheme();
const [{ objectName, viewFields }, setViewFieldsState] =
useRecoilState(viewFieldsState);
const [{ objectName }, setViewFieldsState] = useRecoilState(viewFieldsState);
const viewFields = useRecoilValue(visibleViewFieldsState);
const columnWidths = useRecoilValue(columnWidthByViewFieldIdState);
const addableViewFieldDefinitions = useRecoilValue(
addableViewFieldDefinitionsState,

View File

@ -2,7 +2,7 @@ import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { ViewFieldContext } from '../states/ViewFieldContext';
import { viewFieldsState } from '../states/viewFieldsState';
import { visibleViewFieldsState } from '../states/viewFieldsState';
import { CheckboxCell } from './CheckboxCell';
import { EntityTableCell } from './EntityTableCell';
@ -13,7 +13,7 @@ const StyledRow = styled.tr<{ selected: boolean }>`
`;
export function EntityTableRow({ rowId }: { rowId: string }) {
const { viewFields } = useRecoilValue(viewFieldsState);
const viewFields = useRecoilValue(visibleViewFieldsState);
return (
<StyledRow data-testid={`row-id-${rowId}`} selected={false}>
@ -22,10 +22,7 @@ export function EntityTableRow({ rowId }: { rowId: string }) {
</td>
{viewFields.map((viewField, columnIndex) => {
return (
<ViewFieldContext.Provider
value={viewField}
key={viewField.columnOrder}
>
<ViewFieldContext.Provider value={viewField} key={viewField.id}>
<EntityTableCell cellIndex={columnIndex} />
</ViewFieldContext.Provider>
);

View File

@ -28,7 +28,7 @@ export const toViewFieldInput = (
) => ({
fieldName: viewFieldDefinition.columnLabel,
index: viewFieldDefinition.columnOrder,
isVisible: true,
isVisible: viewFieldDefinition.isVisible ?? true,
objectName,
sizeInPx: viewFieldDefinition.columnSize,
});
@ -64,6 +64,7 @@ export const useLoadView = ({
columnLabel: viewField.fieldName,
columnOrder: viewField.index,
columnSize: viewField.sizeInPx,
isVisible: viewField.isVisible,
}));
setViewFieldsState({ objectName, viewFields });

View File

@ -47,3 +47,15 @@ export const addableViewFieldDefinitionsState = selector({
);
},
});
export const visibleViewFieldsState = selector({
key: 'visibleViewFieldsState',
get: ({ get }) =>
get(viewFieldsState).viewFields.filter((viewField) => viewField.isVisible),
});
export const hiddenViewFieldsState = selector({
key: 'hiddenViewFieldsState',
get: ({ get }) =>
get(viewFieldsState).viewFields.filter((viewField) => !viewField.isVisible),
});

View File

@ -7,6 +7,7 @@ import { SortDropdownButton } from '@/ui/filter-n-sort/components/SortDropdownBu
import { FiltersHotkeyScope } from '@/ui/filter-n-sort/types/FiltersHotkeyScope';
import { SelectedSortType, SortType } from '@/ui/filter-n-sort/types/interface';
import { TopBar } from '@/ui/top-bar/TopBar';
import { OptionsDropdownButton } from '@/views/components/OptionsDropdownButton';
import { TableContext } from '../../states/TableContext';
@ -76,6 +77,9 @@ export function TableHeader<SortField>({
onSortSelect={sortSelect}
HotkeyScope={FiltersHotkeyScope.FilterDropdownButton}
/>
<OptionsDropdownButton
HotkeyScope={FiltersHotkeyScope.FilterDropdownButton}
/>
</>
}
bottomComponent={

View File

@ -91,6 +91,7 @@ export type ViewFieldDefinition<T extends ViewFieldMetadata | unknown> = {
columnOrder: number;
columnIcon?: JSX.Element;
filterIcon?: JSX.Element;
isVisible?: boolean;
metadata: T;
};