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
Branches
Tags
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