1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

feat: add last seen col to admin users list (#949)

* feat: add last seen col to admin users list

* fix: header hover effect, duplicate title from TimeAgo

* fix: use YMD format, never logged

* fix: small tooltip change

* refactor: adapt to review suggestions
This commit is contained in:
Nuno Góis 2022-05-05 14:53:28 +01:00 committed by GitHub
parent 1772997d28
commit 004ded8f74
5 changed files with 57 additions and 6 deletions

View File

@ -16,12 +16,16 @@ export const useStyles = makeStyles()(theme => ({
fontWeight: 'normal',
border: 0,
'&:first-of-type': {
borderTopLeftRadius: '8px',
borderBottomLeftRadius: '8px',
'&, & > button': {
borderTopLeftRadius: theme.spacing(1),
borderBottomLeftRadius: theme.spacing(1),
},
},
'&:last-of-type': {
borderTopRightRadius: '8px',
borderBottomRightRadius: '8px',
'&, & > button': {
borderTopRightRadius: theme.spacing(1),
borderBottomRightRadius: theme.spacing(1),
},
},
},
},

View File

@ -18,6 +18,7 @@ import { ILocationSettings } from 'hooks/useLocationSettings';
import { formatDateYMD } from 'utils/formatDate';
import { Highlighter } from 'component/common/Highlighter/Highlighter';
import { useStyles } from './UserListItem.styles';
import TimeAgo from 'react-timeago';
interface IUserListItemProps {
user: IUser;
@ -40,6 +41,20 @@ const UserListItem = ({
const navigate = useNavigate();
const { classes: styles } = useStyles();
const renderTimeAgo = (date: string) => (
<Tooltip
title={`Last seen on: ${formatDateYMD(
date,
locationSettings.locale
)}`}
arrow
>
<Typography noWrap variant="body2" data-loading>
<TimeAgo date={new Date(date)} live={false} title={''} />
</Typography>
</Tooltip>
);
return (
<TableRow key={user.id} className={styles.tableRow}>
<TableCell className={styles.hideSM}>
@ -77,6 +92,17 @@ const UserListItem = ({
{renderRole(user.rootRole)}
</Typography>
</TableCell>
<TableCell className={styles.hideXS}>
<ConditionallyRender
condition={Boolean(user.seenAt)}
show={() => renderTimeAgo(user.seenAt!)}
elseShow={
<Typography noWrap variant="body2" data-loading>
Never logged
</Typography>
}
/>
</TableCell>
<ConditionallyRender
condition={hasAccess(ADMIN)}
show={

View File

@ -186,6 +186,17 @@ const UsersList = ({ search }: IUsersListProps) => {
>
Role
</TableCellSortable>
<TableCellSortable
className={classnames(
styles.hideXS,
styles.shrinkTableCell
)}
name="last-seen"
sort={sort}
setSort={setSort}
>
Last seen
</TableCellSortable>
<TableCell align="center">
{hasAccess(ADMIN) ? 'Actions' : ''}
</TableCell>

View File

@ -3,7 +3,6 @@ import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
tableCellHeaderSortable: {
padding: 0,
position: 'relative',
cursor: 'pointer',
'& > svg': {
fontSize: 18,

View File

@ -5,7 +5,7 @@ import { createPersistentGlobalStateHook } from './usePersistentGlobalState';
import useUsers from 'hooks/api/getters/useUsers/useUsers';
import IRole from 'interfaces/role';
export type UsersSortType = 'created' | 'name' | 'role';
export type UsersSortType = 'created' | 'name' | 'role' | 'last-seen';
export interface IUsersSort {
type: UsersSortType;
@ -50,6 +50,7 @@ export const createUsersFilterSortOptions = (): IUsersFilterSortOption[] => {
{ type: 'created', name: 'Created' },
{ type: 'name', name: 'Name' },
{ type: 'role', name: 'Role' },
{ type: 'last-seen', name: 'Last seen' },
];
};
@ -65,6 +66,8 @@ const sortAscendingUsers = (
return sortByName(users);
case 'role':
return sortByRole(users, roles);
case 'last-seen':
return sortByLastSeen(users);
default:
console.error(`Unknown feature sort type: ${sort.type}`);
return users;
@ -112,3 +115,11 @@ const getRoleName = (roleId: number, roles: Readonly<IRole[]>) => {
const role = roles.find((role: IRole) => role.id === roleId);
return role ? role.name : '';
};
const sortByLastSeen = (users: Readonly<IUser[]>): IUser[] => {
return [...users].sort((a, b) => {
const aSeenAt = a.seenAt ?? '';
const bSeenAt = b.seenAt ?? '';
return bSeenAt.localeCompare(aSeenAt);
});
};