Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 58 additions & 5 deletions packages/ui/src/views/roles/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
useTheme,
Typography,
Button,
Drawer
Drawer,
TableSortLabel
} from '@mui/material'

// project imports
Expand Down Expand Up @@ -185,6 +186,8 @@ function ShowRoleRow(props) {
const [openViewPermissionsDrawer, setOpenViewPermissionsDrawer] = useState(false)
const [selectedRoleId, setSelectedRoleId] = useState('')
const [assignedUsers, setAssignedUsers] = useState([])
const [order, setOrder] = useState('asc')
const [orderBy, setOrderBy] = useState('workspace')

const theme = useTheme()
const customization = useSelector((state) => state.customization)
Expand All @@ -196,19 +199,53 @@ function ShowRoleRow(props) {
setSelectedRoleId(roleId)
}

const handleRequestSort = (property) => {
const isAsc = orderBy === property && order === 'asc'
setOrder(isAsc ? 'desc' : 'asc')
setOrderBy(property)
}

const sortedAssignedUsers = [...assignedUsers].sort((a, b) => {
let comparison = 0

if (orderBy === 'workspace') {
const workspaceA = (a.workspace?.name || '').toLowerCase()
const workspaceB = (b.workspace?.name || '').toLowerCase()
comparison = workspaceA.localeCompare(workspaceB)
if (comparison === 0) {
const userA = (a.user?.name || a.user?.email || '').toLowerCase()
const userB = (b.user?.name || b.user?.email || '').toLowerCase()
comparison = userA.localeCompare(userB)
}
} else if (orderBy === 'user') {
const userA = (a.user?.name || a.user?.email || '').toLowerCase()
const userB = (b.user?.name || b.user?.email || '').toLowerCase()
comparison = userA.localeCompare(userB)
if (comparison === 0) {
const workspaceA = (a.workspace?.name || '').toLowerCase()
const workspaceB = (b.workspace?.name || '').toLowerCase()
comparison = workspaceA.localeCompare(workspaceB)
}
}

return order === 'asc' ? comparison : -comparison
})
Comment on lines +208 to +232
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The sorting logic is a bit repetitive. You can simplify it to be more concise and adhere to the DRY (Don't Repeat Yourself) principle. By determining the primary and secondary sorting properties based on orderBy first, you can avoid the duplicated if (comparison === 0) blocks and make the code easier to maintain.

    const sortedAssignedUsers = [...assignedUsers].sort((a, b) => {
        const primaryPropA = orderBy === 'workspace' ? a.workspace?.name || '' : a.user?.name || a.user?.email || '';
        const primaryPropB = orderBy === 'workspace' ? b.workspace?.name || '' : b.user?.name || b.user?.email || '';

        const secondaryPropA = orderBy === 'workspace' ? a.user?.name || a.user?.email || '' : a.workspace?.name || '';
        const secondaryPropB = orderBy === 'workspace' ? b.user?.name || b.user?.email || '' : b.workspace?.name || '';

        let comparison = primaryPropA.toLowerCase().localeCompare(primaryPropB.toLowerCase());
        if (comparison === 0) {
            comparison = secondaryPropA.toLowerCase().localeCompare(secondaryPropB.toLowerCase());
        }

        return order === 'asc' ? comparison : -comparison;
    })


useEffect(() => {
if (getAllUsersByRoleIdApi.data) {
setAssignedUsers(getAllUsersByRoleIdApi.data)
}
}, [getAllUsersByRoleIdApi.data])

useEffect(() => {
if (open && selectedRoleId) {
if (openAssignedUsersDrawer && selectedRoleId) {
getAllUsersByRoleIdApi.request(selectedRoleId)
} else {
setOpenAssignedUsersDrawer(false)
setSelectedRoleId('')
setAssignedUsers([])
setOrder('asc')
setOrderBy('workspace')
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [openAssignedUsersDrawer])
Expand Down Expand Up @@ -301,12 +338,28 @@ function ShowRoleRow(props) {
}}
>
<TableRow>
<StyledTableCell sx={{ width: '50%' }}>User</StyledTableCell>
<StyledTableCell sx={{ width: '50%' }}>Workspace</StyledTableCell>
<StyledTableCell sx={{ width: '50%' }}>
<TableSortLabel
active={orderBy === 'user'}
direction={orderBy === 'user' ? order : 'asc'}
onClick={() => handleRequestSort('user')}
>
User
</TableSortLabel>
</StyledTableCell>
<StyledTableCell sx={{ width: '50%' }}>
<TableSortLabel
active={orderBy === 'workspace'}
direction={orderBy === 'workspace' ? order : 'asc'}
onClick={() => handleRequestSort('workspace')}
>
Workspace
</TableSortLabel>
</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{assignedUsers.map((item, index) => (
{sortedAssignedUsers.map((item, index) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using the array index as a key for list items (as seen on the next line: <TableRow key={index}>) is an anti-pattern in React, especially for a list that can be re-ordered by sorting. This can lead to incorrect component state and rendering issues. It's recommended to use a stable, unique identifier from the data itself.

For example, if item has a unique id, you could use key={item.id}. If not, a composite key like key={${item.user.id}-${item.workspace.id}} would be a robust alternative, assuming user and workspace objects have unique ids.

<TableRow key={index}>
<StyledTableCell>{item.user.name || item.user.email}</StyledTableCell>
<StyledTableCell>{item.workspace.name}</StyledTableCell>
Expand Down