diff --git a/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.styles.ts b/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.styles.ts
index 9dd4166c03..026abb9f0d 100644
--- a/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.styles.ts
+++ b/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.styles.ts
@@ -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),
+ },
},
},
},
diff --git a/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.tsx b/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.tsx
index 08246dd354..e0cba8f626 100644
--- a/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.tsx
+++ b/frontend/src/component/admin/users/UsersList/UserListItem/UserListItem.tsx
@@ -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) => (
+
+
+
+
+
+ );
+
return (
@@ -77,6 +92,17 @@ const UserListItem = ({
{renderRole(user.rootRole)}
+
+ renderTimeAgo(user.seenAt!)}
+ elseShow={
+
+ Never logged
+
+ }
+ />
+
{
>
Role
+
+ Last seen
+
{hasAccess(ADMIN) ? 'Actions' : ''}
diff --git a/frontend/src/component/common/Table/TableCellSortable/TableCellSortable.styles.ts b/frontend/src/component/common/Table/TableCellSortable/TableCellSortable.styles.ts
index 4971b723b0..6697522f23 100644
--- a/frontend/src/component/common/Table/TableCellSortable/TableCellSortable.styles.ts
+++ b/frontend/src/component/common/Table/TableCellSortable/TableCellSortable.styles.ts
@@ -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,
diff --git a/frontend/src/hooks/useUsersSort.ts b/frontend/src/hooks/useUsersSort.ts
index e87110379f..1be5596845 100644
--- a/frontend/src/hooks/useUsersSort.ts
+++ b/frontend/src/hooks/useUsersSort.ts
@@ -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) => {
const role = roles.find((role: IRole) => role.id === roleId);
return role ? role.name : '';
};
+
+const sortByLastSeen = (users: Readonly): IUser[] => {
+ return [...users].sort((a, b) => {
+ const aSeenAt = a.seenAt ?? '';
+ const bSeenAt = b.seenAt ?? '';
+ return bSeenAt.localeCompare(aSeenAt);
+ });
+};