Skip to content

feat(permissions): Add sorting feature for Users based on role#7654

Open
afsuyadi wants to merge 1 commit into
Flagsmith:mainfrom
afsuyadi:feat-sorting-users-role
Open

feat(permissions): Add sorting feature for Users based on role#7654
afsuyadi wants to merge 1 commit into
Flagsmith:mainfrom
afsuyadi:feat-sorting-users-role

Conversation

@afsuyadi
Copy link
Copy Markdown

@afsuyadi afsuyadi commented Jun 1, 2026

Thanks for submitting a PR! Please check the boxes below:

  • [✓] I have read the Contributing Guide.
  • [✓] I have added information to docs/ if required so people know about the feature.
  • [✓] I have filled in the "Changes" section below.
  • [✓] I have filled in the "How did you test this code" section below.

Changes

Contributes to #7613

Users in organisation, project, and environment permissions settings can now be sorted by role, making it easy to distinguish admisnitrators from standard users at a glance.

Each user is assigned a role rank for sorting:

  • Organisation Administrator (rank 0)
  • Project / Environment Administrator (rank 1)
  • Standard User (rank 2)

Sorting ASC puts administrators at the top; toggling reverses the order.

How did you test this code?

Tested manually on a local dev environment:

  1. Navigated to Users & Permissions tab
  2. Created users with different roles (Organisation Admin, Standard User)
  3. Clicked the Role sort button - confirmed admins grouped at the top, standard users at the bottom; toggling reversed the order
Screencast+from+01-06-26+14_56_46.mp4

@afsuyadi afsuyadi requested a review from a team as a code owner June 1, 2026 08:17
@afsuyadi afsuyadi requested review from talissoncosta and removed request for a team June 1, 2026 08:17
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

@afsuyadi is attempting to deploy a commit to the Flagsmith Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the front-end Issue related to the React Front End Dashboard label Jun 1, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces role-based sorting for users in both the EditPermissions and OrganisationUsersTable components. The review feedback highlights a performance bottleneck in EditPermissions where an O(N * M) lookup is performed on every render; this can be optimized to O(N + M) by using a Set of admin user IDs. Additionally, the reviewer recommends defining the static sorting options arrays outside of both components to provide stable references and prevent breaking memoization in child components.

Comment on lines +25 to +30
import {
PermissionLevel,
Req,
PermissionRoleType,
SortOrder,
} from 'common/types/requests'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Define the static sorting options array outside of the component to provide a stable reference, preventing unnecessary re-evaluations of memoized hooks in child components.

import {
  PermissionLevel,
  Req,
  PermissionRoleType,
  SortOrder,
} from 'common/types/requests'

const USER_SORT_OPTIONS = [
  {
    label: 'Role',
    order: SortOrder.ASC,
    value: '_roleRank',
  },
]

Comment on lines +1095 to +1103
const usersWithRoleRank = users?.map((user) => ({
...user,
_roleRank:
user.role === 'ADMIN'
? 0
: permissions?.find((p) => p.user.id === user.id)?.admin
? 1
: 2,
}))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current implementation performs an $O(N \times M)$ lookup by calling permissions?.find inside users?.map on every render. For organizations with many users and permissions, this can cause noticeable UI lag.

We can optimize this to $O(N + M)$ by creating a Set of admin user IDs before mapping. Additionally, we should safely access p.user?.id to prevent potential runtime errors if p.user is undefined.

              const adminUserIds = new Set(
                permissions
                  ?.filter((p) => p.admin && p.user?.id)
                  .map((p) => p.user.id) || []
              )
              const usersWithRoleRank = users?.map((user) => ({
                ...user,
                _roleRank:
                  user.role === 'ADMIN'
                    ? 0
                    : adminUserIds.has(user.id)
                    ? 1
                    : 2,
              }))

Comment on lines +1120 to +1126
sorting={[
{
label: 'Role',
order: SortOrder.ASC,
value: '_roleRank',
},
]}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use the static USER_SORT_OPTIONS constant defined outside the component to maintain a stable reference and avoid breaking memoization in PanelSearch.

                          sorting={USER_SORT_OPTIONS}

Comment on lines +14 to 15
import { SortOrder } from 'common/types/requests'
interface OrganisationUsersTableProps {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Define the static sorting options array outside of the component to provide a stable reference, preventing unnecessary re-evaluations of memoized hooks in child components.

import { SortOrder } from 'common/types/requests'

const ROLE_SORT_OPTIONS = [
  {
    label: 'Role',
    order: SortOrder.ASC,
    value: 'role',
  },
]
interface OrganisationUsersTableProps {

Comment on lines +99 to +105
sorting={[
{
label: 'Role',
order: SortOrder.ASC,
value: 'role',
},
]}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use the static ROLE_SORT_OPTIONS constant defined outside the component to maintain a stable reference and avoid breaking memoization in PanelSearch.

      sorting={ROLE_SORT_OPTIONS}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants