Skip to content
Snippets Groups Projects
Commit 5b0ddd41 authored by Bjarke Madsen's avatar Bjarke Madsen
Browse files

Add sorting of users in the user management page

parent caab071d
No related branches found
No related tags found
1 merge request!75Add sorting of users in the user management page
Source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
This diff is collapsed.
......@@ -49,11 +49,30 @@ const updateUser = async (id, changes) => {
return data.user;
};
const defaultSortFunction = (a, b) => {
if (a.permissions.active && !b.permissions.active) {
return -1;
} else if (!a.permissions.active && b.permissions.active) {
return 1;
} else if (a.permissions.active && b.permissions.active) {
if (a.role === 'admin' && b.role === 'user') {
return 1;
} else if (a.role === 'user' && b.role === 'admin') {
return -1;
} else {
return a.name.localeCompare(b.name)
}
} else {
return a.name.localeCompare(b.name)
}
}
function UserManagementComponent() {
const [users, setUsers] = useState<User[]>([]);
const [nrens, setNrens] = useState<Nren[]>([]);
const { user: loggedInUser } = useContext(userContext);
const [sortFunc, setSortFunc] = useState({ idx: -1, func: defaultSortFunction, asc: true });
useEffect(() => {
fetchUsers().then((userList) => {
......@@ -61,7 +80,7 @@ function UserManagementComponent() {
});
fetchNrens().then((nrenList) => {
setNrens(nrenList.sort((a, b) => a.name.localeCompare(b.name)))
setNrens(nrenList)//.sort((a, b) => a.name.localeCompare(b.name)))
})
}, []);
......@@ -93,6 +112,86 @@ function UserManagementComponent() {
})?.id
}
const sortedUsers = users.sort(sortFunc.func);
const setSort = (index) => {
if (index === sortFunc.idx || ((index === 5 || index === 0) && sortFunc.idx === -1)) {
// reverse sort
if (index === 5 || index === 0) {
// hack not to show the sort icon on column 0 and 5
index = -1
}
setSortFunc({ idx: index, asc: !sortFunc.asc, func: (a, b) => sortFunc.func(b, a) })
return
}
if (index === 0) {
// user ID is a UUID which is meaningless to sort by, so use default sort function
setSortFunc({ idx: -1, asc: true, func: defaultSortFunction })
} else if (index === 1) {
// sort by active
setSortFunc({
idx: index, asc: true, func: (a, b) => {
if (a.permissions.active && !b.permissions.active) {
return -1;
} else if (!a.permissions.active && b.permissions.active) {
return 1;
} else {
return 0;
}
}
})
} else if (index === 2) {
// sort by role
setSortFunc({
idx: index, asc: true, func: (a, b) => {
return a.role.localeCompare(b.role)
}
})
} else if (index === 3) {
// sort by email
setSortFunc({
idx: index, asc: true, func: (a, b) => {
return a.email.localeCompare(b.email)
}
})
} else if (index === 4) {
// sort by name
setSortFunc({
idx: index, asc: true, func: (a, b) => {
return a.name.localeCompare(b.name)
}
})
} else if (index === 5) {
// use the default sort function, OIDC sub has no meaning when sorting
setSortFunc({ idx: -1, asc: true, func: defaultSortFunction })
} else if (index === 6) {
// sort by NREN
setSortFunc({
idx: index, asc: true, func: (a, b) => {
if (a.nrens.length === 0 && b.nrens.length === 0) {
return 0;
} else if (a.nrens.length === 0) {
return -1;
} else if (b.nrens.length === 0) {
return 1;
} else {
return a.nrens[0].localeCompare(b.nrens[0])
}
}
})
} else {
setSortFunc({ idx: index, asc: true, func: defaultSortFunction })
}
}
// build the aria-sort attribute for each column with spreadable objects..
// this is apparently the easiest way to do it conditionally
const ariaSort = {}
for (let i = 0; i <= 6; i++) {
ariaSort[i] = sortFunc.idx === i ? ({ 'aria-sort': sortFunc.asc ? 'ascending' : 'descending' }) : null
}
return (
<Container style={{ maxWidth: '90vw', }}>
<Row>
......@@ -100,17 +199,17 @@ function UserManagementComponent() {
<Table>
<thead>
<tr>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>Id</th>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>Active</th>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>Role</th>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>Email</th>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>Full Name</th>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>OIDC Sub</th>
<th className='pt-3' style={{ border: "1px solid #ddd" }}>NREN</th>
<th {...ariaSort[0]} onClick={() => setSort(0)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>Id</th>
<th {...ariaSort[1]} onClick={() => setSort(1)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>Active</th>
<th {...ariaSort[2]} onClick={() => setSort(2)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>Role</th>
<th {...ariaSort[3]} onClick={() => setSort(3)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>Email</th>
<th {...ariaSort[4]} onClick={() => setSort(4)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>Full Name</th>
<th {...ariaSort[5]} onClick={() => setSort(5)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>OIDC Sub</th>
<th {...ariaSort[6]} onClick={() => setSort(6)} className='pt-3 sortable' style={{ border: "1px solid #ddd" }}>NREN</th>
</tr>
</thead>
<tbody>
{users.map(user => (
{sortedUsers.map(user => (
<tr key={user.id}>
<td style={{ border: "1px dotted #ddd" }}>{user.id}</td>
<td style={{ border: "1px dotted #ddd" }}>
......
......@@ -182,3 +182,25 @@
.survey-tooltip:hover::before {
display: block;
}
.sortable {
cursor: pointer;
}
.sortable:hover {
text-decoration: dotted underline;
}
th.sortable[aria-sort="descending"]::after {
content: "▼";
color: currentcolor;
font-size: 100%;
margin-left: 0.25rem;
}
th.sortable[aria-sort="ascending"]::after {
content: "▲";
color: currentcolor;
font-size: 100%;
margin-left: 0.25rem;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment