mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Feat/groups refinements (#1197)
* Improvements * Double icon for group * Hide columns * Refinements * Refinements * Reduce padding * Add projectId * Fixes * Make useHiddenColumns component
This commit is contained in:
		
							parent
							
								
									6eb3922741
								
							
						
					
					
						commit
						c99470ec4e
					
				| @ -18,18 +18,19 @@ import { CopyApiTokenButton } from 'component/admin/apiToken/CopyApiTokenButton/ | ||||
| import { RemoveApiTokenButton } from 'component/admin/apiToken/RemoveApiTokenButton/RemoveApiTokenButton'; | ||||
| import { DateCell } from 'component/common/Table/cells/DateCell/DateCell'; | ||||
| import { sortTypes } from 'utils/sortTypes'; | ||||
| import { useEffect, useMemo } from 'react'; | ||||
| import { useMemo } from 'react'; | ||||
| import theme from 'themes/theme'; | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| import { ProjectsList } from 'component/admin/apiToken/ProjectsList/ProjectsList'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { HighlightCell } from 'component/common/Table/cells/HighlightCell/HighlightCell'; | ||||
| import { Search } from 'component/common/Search/Search'; | ||||
| import useHiddenColumns from 'hooks/useHiddenColumns'; | ||||
| 
 | ||||
| export const ApiTokenTable = () => { | ||||
|     const { tokens, loading } = useApiTokens(); | ||||
|     const hiddenColumns = useHiddenColumns(); | ||||
|     const initialState = useMemo(() => ({ sortBy: [{ id: 'createdAt' }] }), []); | ||||
|     const { uiConfig } = useUiConfig(); | ||||
| 
 | ||||
|     const { | ||||
|         getTableProps, | ||||
| @ -52,9 +53,16 @@ export const ApiTokenTable = () => { | ||||
|         useSortBy | ||||
|     ); | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         setHiddenColumns(hiddenColumns); | ||||
|     }, [setHiddenColumns, hiddenColumns]); | ||||
|     useHiddenColumns( | ||||
|         setHiddenColumns, | ||||
|         ['Icon', 'createdAt'], | ||||
|         useMediaQuery(theme.breakpoints.down('md')) | ||||
|     ); | ||||
|     useHiddenColumns( | ||||
|         setHiddenColumns, | ||||
|         ['projects', 'environment'], | ||||
|         !uiConfig.flags.E | ||||
|     ); | ||||
| 
 | ||||
|     return ( | ||||
|         <PageContent | ||||
| @ -124,27 +132,6 @@ export const ApiTokenTable = () => { | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| const useHiddenColumns = (): string[] => { | ||||
|     const { uiConfig } = useUiConfig(); | ||||
|     const isMediumScreen = useMediaQuery(theme.breakpoints.down('md')); | ||||
| 
 | ||||
|     return useMemo(() => { | ||||
|         const hidden: string[] = []; | ||||
| 
 | ||||
|         if (!uiConfig.flags.E) { | ||||
|             hidden.push('projects'); | ||||
|             hidden.push('environment'); | ||||
|         } | ||||
| 
 | ||||
|         if (isMediumScreen) { | ||||
|             hidden.push('Icon'); | ||||
|             hidden.push('createdAt'); | ||||
|         } | ||||
| 
 | ||||
|         return hidden; | ||||
|     }, [uiConfig, isMediumScreen]); | ||||
| }; | ||||
| 
 | ||||
| const COLUMNS = [ | ||||
|     { | ||||
|         id: 'Icon', | ||||
|  | ||||
| @ -1,13 +1,12 @@ | ||||
| import { useEffect, useMemo, useState, VFC } from 'react'; | ||||
| import { | ||||
|     Button, | ||||
|     IconButton, | ||||
|     styled, | ||||
|     Tooltip, | ||||
|     useMediaQuery, | ||||
|     useTheme, | ||||
| } from '@mui/material'; | ||||
| import { useSearchParams } from 'react-router-dom'; | ||||
| import { useSearchParams, Link } from 'react-router-dom'; | ||||
| import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table'; | ||||
| import { TablePlaceholder, VirtualizedTable } from 'component/common/Table'; | ||||
| import { useGroup } from 'hooks/api/getters/useGroup/useGroup'; | ||||
| @ -26,17 +25,17 @@ import { HighlightCell } from 'component/common/Table/cells/HighlightCell/Highli | ||||
| import { TimeAgoCell } from 'component/common/Table/cells/TimeAgoCell/TimeAgoCell'; | ||||
| import { GroupUserRoleCell } from 'component/admin/groups/GroupUserRoleCell/GroupUserRoleCell'; | ||||
| import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; | ||||
| import { Delete, Edit } from '@mui/icons-material'; | ||||
| import { Add, Delete, Edit } from '@mui/icons-material'; | ||||
| import { ADMIN } from 'component/providers/AccessProvider/permissions'; | ||||
| import { MainHeader } from 'component/common/MainHeader/MainHeader'; | ||||
| import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; | ||||
| import { RemoveGroup } from 'component/admin/groups/RemoveGroup/RemoveGroup'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell'; | ||||
| import { AddGroupUser } from './AddGroupUser/AddGroupUser'; | ||||
| import { EditGroupUser } from './EditGroupUser/EditGroupUser'; | ||||
| import { RemoveGroupUser } from './RemoveGroupUser/RemoveGroupUser'; | ||||
| import { UserAvatar } from 'component/common/UserAvatar/UserAvatar'; | ||||
| import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton'; | ||||
| import { | ||||
|     UG_EDIT_BTN_ID, | ||||
|     UG_DELETE_BTN_ID, | ||||
| @ -140,8 +139,10 @@ export const Group: VFC = () => { | ||||
|                 Cell: ({ row: { original: rowUser } }: any) => ( | ||||
|                     <ActionCell> | ||||
|                         <Tooltip title="Edit user" arrow describeChild> | ||||
|                             <span> | ||||
|                                 <IconButton | ||||
|                                     data-testid={`${UG_EDIT_USER_BTN_ID}-${rowUser.id}`} | ||||
|                                     disabled={group?.users.length === 1} | ||||
|                                     onClick={() => { | ||||
|                                         setSelectedUser(rowUser); | ||||
|                                         setEditUserOpen(true); | ||||
| @ -149,14 +150,17 @@ export const Group: VFC = () => { | ||||
|                                 > | ||||
|                                     <Edit /> | ||||
|                                 </IconButton> | ||||
|                             </span> | ||||
|                         </Tooltip> | ||||
|                         <Tooltip | ||||
|                             title="Remove user from group" | ||||
|                             arrow | ||||
|                             describeChild | ||||
|                         > | ||||
|                             <span> | ||||
|                                 <IconButton | ||||
|                                     data-testid={`${UG_REMOVE_USER_BTN_ID}-${rowUser.id}`} | ||||
|                                     disabled={group?.users.length === 1} | ||||
|                                     onClick={() => { | ||||
|                                         setSelectedUser(rowUser); | ||||
|                                         setRemoveUserOpen(true); | ||||
| @ -164,6 +168,7 @@ export const Group: VFC = () => { | ||||
|                                 > | ||||
|                                     <Delete /> | ||||
|                                 </IconButton> | ||||
|                             </span> | ||||
|                         </Tooltip> | ||||
|                     </ActionCell> | ||||
|                 ), | ||||
| @ -171,7 +176,7 @@ export const Group: VFC = () => { | ||||
|                 disableSortBy: true, | ||||
|             }, | ||||
|         ], | ||||
|         [setSelectedUser, setRemoveUserOpen] | ||||
|         [setSelectedUser, setRemoveUserOpen, group?.users.length] | ||||
|     ); | ||||
| 
 | ||||
|     const [searchParams, setSearchParams] = useSearchParams(); | ||||
| @ -306,16 +311,17 @@ export const Group: VFC = () => { | ||||
|                                                 </> | ||||
|                                             } | ||||
|                                         /> | ||||
|                                         <Button | ||||
|                                         <ResponsiveButton | ||||
|                                             data-testid={UG_ADD_USER_BTN_ID} | ||||
|                                             variant="contained" | ||||
|                                             color="primary" | ||||
|                                             onClick={() => { | ||||
|                                                 setAddUserOpen(true); | ||||
|                                             }} | ||||
|                                             maxWidth="700px" | ||||
|                                             Icon={Add} | ||||
|                                             permission={ADMIN} | ||||
|                                         > | ||||
|                                             Add user | ||||
|                                         </Button> | ||||
|                                         </ResponsiveButton> | ||||
|                                     </> | ||||
|                                 } | ||||
|                             > | ||||
| @ -376,13 +382,13 @@ export const Group: VFC = () => { | ||||
|                         <EditGroupUser | ||||
|                             open={editUserOpen} | ||||
|                             setOpen={setEditUserOpen} | ||||
|                             user={selectedUser!} | ||||
|                             user={selectedUser} | ||||
|                             group={group!} | ||||
|                         /> | ||||
|                         <RemoveGroupUser | ||||
|                             open={removeUserOpen} | ||||
|                             setOpen={setRemoveUserOpen} | ||||
|                             user={selectedUser!} | ||||
|                             user={selectedUser} | ||||
|                             group={group!} | ||||
|                         /> | ||||
|                     </PageContent> | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { useMemo, VFC } from 'react'; | ||||
| import { IconButton, Tooltip } from '@mui/material'; | ||||
| import { IconButton, Tooltip, useMediaQuery } from '@mui/material'; | ||||
| import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; | ||||
| import { IGroupUser } from 'interfaces/group'; | ||||
| import { HighlightCell } from 'component/common/Table/cells/HighlightCell/HighlightCell'; | ||||
| @ -11,6 +11,8 @@ import { VirtualizedTable } from 'component/common/Table'; | ||||
| import { useFlexLayout, useSortBy, useTable } from 'react-table'; | ||||
| import { sortTypes } from 'utils/sortTypes'; | ||||
| import { UserAvatar } from 'component/common/UserAvatar/UserAvatar'; | ||||
| import theme from 'themes/theme'; | ||||
| import useHiddenColumns from 'hooks/useHiddenColumns'; | ||||
| 
 | ||||
| interface IGroupFormUsersTableProps { | ||||
|     users: IGroupUser[]; | ||||
| @ -106,7 +108,7 @@ export const GroupFormUsersTable: VFC<IGroupFormUsersTableProps> = ({ | ||||
|         [setUsers] | ||||
|     ); | ||||
| 
 | ||||
|     const { headerGroups, rows, prepareRow } = useTable( | ||||
|     const { headerGroups, rows, prepareRow, setHiddenColumns } = useTable( | ||||
|         { | ||||
|             columns: columns as any[], | ||||
|             data: users as any[], | ||||
| @ -119,6 +121,12 @@ export const GroupFormUsersTable: VFC<IGroupFormUsersTableProps> = ({ | ||||
|         useFlexLayout | ||||
|     ); | ||||
| 
 | ||||
|     useHiddenColumns( | ||||
|         setHiddenColumns, | ||||
|         ['imageUrl', 'name'], | ||||
|         useMediaQuery(theme.breakpoints.down('md')) | ||||
|     ); | ||||
| 
 | ||||
|     return ( | ||||
|         <ConditionallyRender | ||||
|             condition={rows.length > 0} | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { useEffect, useMemo, useState, VFC } from 'react'; | ||||
| import { useGroups } from 'hooks/api/getters/useGroups/useGroups'; | ||||
| import { Link, useSearchParams } from 'react-router-dom'; | ||||
| import { Link, useNavigate, useSearchParams } from 'react-router-dom'; | ||||
| import { IGroup } from 'interfaces/group'; | ||||
| import { PageContent } from 'component/common/PageContent/PageContent'; | ||||
| import { PageHeader } from 'component/common/PageHeader/PageHeader'; | ||||
| @ -12,6 +12,9 @@ import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightC | ||||
| import { TablePlaceholder } from 'component/common/Table'; | ||||
| import { GroupCard } from './GroupCard/GroupCard'; | ||||
| import { GroupEmpty } from './GroupEmpty/GroupEmpty'; | ||||
| import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton'; | ||||
| import { ADMIN } from 'component/providers/AccessProvider/permissions'; | ||||
| import { Add } from '@mui/icons-material'; | ||||
| import { NAVIGATE_TO_CREATE_GROUP } from 'utils/testIds'; | ||||
| 
 | ||||
| type PageQueryType = Partial<Record<'search', string>>; | ||||
| @ -33,6 +36,7 @@ const groupsSearch = (group: IGroup, searchValue: string) => { | ||||
| }; | ||||
| 
 | ||||
| export const GroupsList: VFC = () => { | ||||
|     const navigate = useNavigate(); | ||||
|     const { groups = [], loading } = useGroups(); | ||||
|     const [searchParams, setSearchParams] = useSearchParams(); | ||||
|     const [searchValue, setSearchValue] = useState( | ||||
| @ -81,15 +85,17 @@ export const GroupsList: VFC = () => { | ||||
|                                     </> | ||||
|                                 } | ||||
|                             /> | ||||
|                             <Button | ||||
|                                 to="/admin/groups/create-group" | ||||
|                                 component={Link} | ||||
|                                 variant="contained" | ||||
|                                 color="primary" | ||||
|                             <ResponsiveButton | ||||
|                                 onClick={() => | ||||
|                                     navigate('/admin/groups/create-group') | ||||
|                                 } | ||||
|                                 maxWidth="700px" | ||||
|                                 Icon={Add} | ||||
|                                 permission={ADMIN} | ||||
|                                 data-testid={NAVIGATE_TO_CREATE_GROUP} | ||||
|                             > | ||||
|                                 New group | ||||
|                             </Button> | ||||
|                             </ResponsiveButton> | ||||
|                         </> | ||||
|                     } | ||||
|                 > | ||||
|  | ||||
| @ -13,7 +13,7 @@ const StyledMainHeader = styled(Paper)(({ theme }) => ({ | ||||
| 
 | ||||
| const StyledTitleHeader = styled('div')(({ theme }) => ({ | ||||
|     display: 'flex', | ||||
|     alignItems: 'center', | ||||
|     alignItems: 'flex-start', | ||||
|     justifyContent: 'space-between', | ||||
| })); | ||||
| 
 | ||||
|  | ||||
| @ -47,8 +47,8 @@ const StyledAutocompleteWrapper = styled('div')(({ theme }) => ({ | ||||
|     }, | ||||
| })); | ||||
| 
 | ||||
| const StyledButtonContainer = styled('div')(() => ({ | ||||
|     marginTop: 'auto', | ||||
| const StyledButtonContainer = styled('div')(({ theme }) => ({ | ||||
|     marginTop: theme.spacing(6), | ||||
|     display: 'flex', | ||||
|     justifyContent: 'flex-end', | ||||
| })); | ||||
|  | ||||
| @ -9,7 +9,7 @@ const StyledDescription = styled('div')(({ theme }) => ({ | ||||
|     padding: theme.spacing(3), | ||||
|     backgroundColor: theme.palette.neutral.light, | ||||
|     color: theme.palette.text.secondary, | ||||
|     fontSize: theme.fontSizes.smallerBody, | ||||
|     fontSize: theme.fontSizes.smallBody, | ||||
|     borderRadius: theme.shape.borderRadiusMedium, | ||||
| })); | ||||
| 
 | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| import { useEffect, useMemo, useState, VFC } from 'react'; | ||||
| import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table'; | ||||
| import { VirtualizedTable, TablePlaceholder } from 'component/common/Table'; | ||||
| import { Button, useMediaQuery, useTheme } from '@mui/material'; | ||||
| import { Delete, Edit } from '@mui/icons-material'; | ||||
| import { styled, useMediaQuery, useTheme } from '@mui/material'; | ||||
| import { Add, Delete, Edit } from '@mui/icons-material'; | ||||
| import { sortTypes } from 'utils/sortTypes'; | ||||
| import useProjectAccess, { | ||||
|     ENTITY_TYPE, | ||||
| @ -38,9 +38,11 @@ import { IUser } from 'interfaces/user'; | ||||
| import { IGroup } from 'interfaces/group'; | ||||
| import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; | ||||
| import { UserAvatar } from 'component/common/UserAvatar/UserAvatar'; | ||||
| import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton'; | ||||
| import { ProjectAccessCreate } from 'component/project/ProjectAccess/ProjectAccessCreate/ProjectAccessCreate'; | ||||
| import { ProjectAccessEditUser } from 'component/project/ProjectAccess/ProjectAccessEditUser/ProjectAccessEditUser'; | ||||
| import { ProjectAccessEditGroup } from 'component/project/ProjectAccess/ProjectAccessEditGroup/ProjectAccessEditGroup'; | ||||
| import useHiddenColumns from 'hooks/useHiddenColumns'; | ||||
| 
 | ||||
| export type PageQueryType = Partial< | ||||
|     Record<'sort' | 'order' | 'search', string> | ||||
| @ -53,6 +55,20 @@ const { value: storedParams, setValue: setStoredParams } = createLocalStorage( | ||||
|     defaultSort | ||||
| ); | ||||
| 
 | ||||
| const StyledUserAvatars = styled('div')(({ theme }) => ({ | ||||
|     display: 'inline-flex', | ||||
|     alignItems: 'center', | ||||
|     flexWrap: 'wrap', | ||||
|     marginLeft: theme.spacing(1), | ||||
| })); | ||||
| 
 | ||||
| const StyledEmptyAvatar = styled(UserAvatar)(({ theme }) => ({ | ||||
|     marginRight: theme.spacing(-3.5), | ||||
| })); | ||||
| const StyledGroupAvatar = styled(UserAvatar)(({ theme }) => ({ | ||||
|     outline: `${theme.spacing(0.25)} solid ${theme.palette.background.paper}`, | ||||
| })); | ||||
| 
 | ||||
| export const ProjectAccessTable: VFC = () => { | ||||
|     const projectId = useRequiredPathParam('projectId'); | ||||
| 
 | ||||
| @ -77,11 +93,15 @@ export const ProjectAccessTable: VFC = () => { | ||||
|                 Header: 'Avatar', | ||||
|                 accessor: 'imageUrl', | ||||
|                 Cell: ({ row: { original: row } }: any) => ( | ||||
|                     <TextCell> | ||||
|                         <UserAvatar user={row.entity}> | ||||
|                     <StyledUserAvatars> | ||||
|                         <ConditionallyRender | ||||
|                             condition={row.type === ENTITY_TYPE.GROUP} | ||||
|                             show={<StyledEmptyAvatar />} | ||||
|                         /> | ||||
|                         <StyledGroupAvatar user={row.entity}> | ||||
|                             {row.entity.users?.length} | ||||
|                         </UserAvatar> | ||||
|                     </TextCell> | ||||
|                         </StyledGroupAvatar> | ||||
|                     </StyledUserAvatars> | ||||
|                 ), | ||||
|                 maxWidth: 85, | ||||
|                 disableSortBy: true, | ||||
| @ -124,6 +144,7 @@ export const ProjectAccessTable: VFC = () => { | ||||
|                 searchable: true, | ||||
|             }, | ||||
|             { | ||||
|                 id: 'role', | ||||
|                 Header: 'Role', | ||||
|                 accessor: (row: IProjectAccess) => | ||||
|                     access?.roles.find(({ id }) => id === row.entity.roleId) | ||||
| @ -145,6 +166,7 @@ export const ProjectAccessTable: VFC = () => { | ||||
|                 maxWidth: 150, | ||||
|             }, | ||||
|             { | ||||
|                 id: 'lastLogin', | ||||
|                 Header: 'Last login', | ||||
|                 accessor: (row: IProjectAccess) => { | ||||
|                     if (row.type === ENTITY_TYPE.USER) { | ||||
| @ -240,6 +262,7 @@ export const ProjectAccessTable: VFC = () => { | ||||
|         headerGroups, | ||||
|         rows, | ||||
|         prepareRow, | ||||
|         setHiddenColumns, | ||||
|         state: { sortBy }, | ||||
|     } = useTable( | ||||
|         { | ||||
| @ -258,6 +281,12 @@ export const ProjectAccessTable: VFC = () => { | ||||
|         useFlexLayout | ||||
|     ); | ||||
| 
 | ||||
|     useHiddenColumns( | ||||
|         setHiddenColumns, | ||||
|         ['imageUrl', 'username', 'role', 'added', 'lastLogin'], | ||||
|         isSmallScreen | ||||
|     ); | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         const tableState: PageQueryType = {}; | ||||
|         tableState.sort = sortBy[0].id; | ||||
| @ -332,14 +361,15 @@ export const ProjectAccessTable: VFC = () => { | ||||
|                                     </> | ||||
|                                 } | ||||
|                             /> | ||||
|                             <Button | ||||
|                                 component={Link} | ||||
|                                 to={`create`} | ||||
|                                 variant="contained" | ||||
|                                 color="primary" | ||||
|                             <ResponsiveButton | ||||
|                                 onClick={() => navigate('create')} | ||||
|                                 maxWidth="700px" | ||||
|                                 Icon={Add} | ||||
|                                 permission={UPDATE_PROJECT} | ||||
|                                 projectId={projectId} | ||||
|                             > | ||||
|                                 Assign {entityType} | ||||
|                             </Button> | ||||
|                             </ResponsiveButton> | ||||
|                         </> | ||||
|                     } | ||||
|                 > | ||||
|  | ||||
| @ -20,17 +20,22 @@ import { IGroup, IGroupUser } from 'interfaces/group'; | ||||
| import { VFC, useState } from 'react'; | ||||
| import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table'; | ||||
| import { sortTypes } from 'utils/sortTypes'; | ||||
| import useHiddenColumns from 'hooks/useHiddenColumns'; | ||||
| 
 | ||||
| const StyledPageContent = styled(PageContent)(({ theme }) => ({ | ||||
|     height: '100vh', | ||||
|     overflow: 'auto', | ||||
|     padding: theme.spacing(7.5, 6), | ||||
|     [theme.breakpoints.down('md')]: { | ||||
|         padding: theme.spacing(4, 2), | ||||
|     }, | ||||
|     '& .header': { | ||||
|         padding: theme.spacing(0, 0, 2, 0), | ||||
|     }, | ||||
|     '& .body': { | ||||
|         padding: theme.spacing(3, 0, 0, 0), | ||||
|     }, | ||||
|     borderRadius: `${theme.spacing(1.5, 0, 0, 1.5)} !important`, | ||||
| })); | ||||
| 
 | ||||
| const StyledTitle = styled('div')(({ theme }) => ({ | ||||
| @ -38,7 +43,7 @@ const StyledTitle = styled('div')(({ theme }) => ({ | ||||
|     flexDirection: 'column', | ||||
|     '& > span': { | ||||
|         color: theme.palette.text.secondary, | ||||
|         fontSize: theme.fontSizes.smallBody, | ||||
|         fontSize: theme.fontSizes.bodySize, | ||||
|     }, | ||||
| })); | ||||
| 
 | ||||
| @ -80,6 +85,7 @@ const columns = [ | ||||
|         filterName: 'type', | ||||
|     }, | ||||
|     { | ||||
|         id: 'joined', | ||||
|         Header: 'Joined', | ||||
|         accessor: 'joinedAt', | ||||
|         Cell: DateCell, | ||||
| @ -87,6 +93,7 @@ const columns = [ | ||||
|         maxWidth: 150, | ||||
|     }, | ||||
|     { | ||||
|         id: 'lastLogin', | ||||
|         Header: 'Last login', | ||||
|         accessor: (row: IGroupUser) => row.seenAt || '', | ||||
|         Cell: ({ row: { original: user } }: any) => ( | ||||
| @ -135,7 +142,7 @@ export const ProjectGroupView: VFC<IProjectGroupViewProps> = ({ | ||||
|         group?.users ?? [] | ||||
|     ); | ||||
| 
 | ||||
|     const { headerGroups, rows, prepareRow } = useTable( | ||||
|     const { headerGroups, rows, prepareRow, setHiddenColumns } = useTable( | ||||
|         { | ||||
|             columns: columns as any[], | ||||
|             data, | ||||
| @ -149,6 +156,12 @@ export const ProjectGroupView: VFC<IProjectGroupViewProps> = ({ | ||||
|         useFlexLayout | ||||
|     ); | ||||
| 
 | ||||
|     useHiddenColumns( | ||||
|         setHiddenColumns, | ||||
|         ['imageUrl', 'name', 'joined', 'lastLogin'], | ||||
|         useMediaQuery(theme.breakpoints.down('md')) | ||||
|     ); | ||||
| 
 | ||||
|     return ( | ||||
|         <SidebarModal | ||||
|             open={open} | ||||
|  | ||||
							
								
								
									
										15
									
								
								frontend/src/hooks/useHiddenColumns.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								frontend/src/hooks/useHiddenColumns.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import { useEffect } from 'react'; | ||||
| import { IdType } from 'react-table'; | ||||
| 
 | ||||
| const useHiddenColumns = ( | ||||
|     setHiddenColumns: <D>(param: Array<IdType<D>>) => void, | ||||
|     hiddenColumns: string[], | ||||
|     condition: boolean | ||||
| ) => { | ||||
|     useEffect(() => { | ||||
|         const hidden = condition ? hiddenColumns : []; | ||||
|         setHiddenColumns(hidden); | ||||
|     }, [setHiddenColumns, condition]); | ||||
| }; | ||||
| 
 | ||||
| export default useHiddenColumns; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user