Page MenuHomePhabricator

[web] Create a 'create role' modal to allow users to make custom roles
ClosedPublic

Authored by rohan on Jul 21 2023, 9:09 AM.
Tags
None
Referenced Files
F2062238: D8594.id29399.diff
Fri, Jun 21, 1:39 AM
Unknown Object (File)
Wed, Jun 19, 8:27 AM
Unknown Object (File)
Wed, Jun 19, 1:58 AM
Unknown Object (File)
Mon, Jun 17, 9:12 AM
Unknown Object (File)
Sun, Jun 16, 4:07 AM
Unknown Object (File)
Thu, Jun 13, 11:54 PM
Unknown Object (File)
Thu, Jun 13, 8:50 PM
Unknown Object (File)
Thu, Jun 13, 4:31 PM

Details

Summary

This is the screen to allow users to create a custom role. For now, this is used just to create a new role, but later on in the web stack this screen should be able to be re-used for the editing roles flow. The logic of iterating through user-surfaced permissions is similar to what is done on native in D8391.

The on save functionality will come in the next diff. Also, the reason for making onCloseModal is because later in the stack, I will be pushing an UnsavedChangesModal if there are any changes made if a user tries to exit, so I just set it up now.

Additional note: any common / shared logic between web and native are tracked to be extracted to a shared utils file in
https://linear.app/comm/issue/ENG-4443/[follow-up]-extract-shared-logic-between-web-and-native-to-utils to not delay this goal.

ENG-4427

Depends on D8593

Test Plan

Walked through the create role flow with the new modal and confirmed everything worked (role name field, selecting permissions, clearing permissions, etc).

Diff Detail

Repository
rCOMM Comm
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

rohan edited the test plan for this revision. (Show Details)
rohan requested review of this revision.Jul 21 2023, 9:30 AM
atul requested changes to this revision.Jul 26 2023, 2:19 PM

Let's see if we can

  1. Use a $ReadOnlySet instead of $ReadOnlyArray for pendingRolePermissions.
  2. Break apart modifyUserSurfacedPermissionOptions(...) into separate functions with clear and descriptive names.
web/roles/community-roles-modal.react.js
60 ↗(On Diff #28944)

Should we put some sort of TODO comment or something here?

web/roles/create-roles-modal.css
41 ↗(On Diff #28944)

Thanks for using CSS variables for all font sizes/colors

web/roles/create-roles-modal.react.js
33–34 ↗(On Diff #28944)

Does the order of elements in this array matter at all?

If not, should we just use a $ReadOnlySet anytime we have a collection of UserSurfacedPermissions?

43–46 ↗(On Diff #28944)

Caught

Also, the reason for making onCloseModal is because later in the stack, I will be pushing an UnsavedChangesModal if there are any changes made if a user tries to exit, so I just set it up now.

in the diff Summary, but in future might be helpful to annotate this directly to put it "right in reviewers face."

48–50 ↗(On Diff #28944)

Could probably consolidate these types into 2 instead of 3 by making css.clearPermissions the "enabled" style and optionally toggling the "disabled" style based on pendingRolePermissions.length.

const clearPermissionsClassNames = classNames({
   [css.clearPermissions]: true,
   [css.clearPermissionsDisabled]: pendingRolePermissions.length === 0,
 });

Doesn't really matter though, totally fine as is

58–62 ↗(On Diff #28944)

We could make this O(1) instead of O(n) if pendingRolePermissions was a $ReadOnlySet instead of $ReadOnlyArray.

Again, probably won't make a huge difference in practice... but it's easy enough to change.

66–74 ↗(On Diff #28944)

If we were to use a $ReadOnlySet, we could do something like:

setPendingRolePermissions(currentPermissions => {
   if (currentPermissions.has(option.userSurfacedPermission)) {
     const newPermissions = new Set(currentPermissions);
     newPermissions.delete(option.userSurfacedPermission);
     return newPermissions;
   } else {
     return new Set([...currentPermissions, option.userSurfacedPermission]);
   }
})

which imo is a bit more readable

78–81 ↗(On Diff #28944)

It's not clear what's happening here. What exactly is modifyUserSurfacedPermissionOptions modifying? Why is it making those modifications?

web/roles/role-utils.react.js
19 ↗(On Diff #28944)

The function's purpose isn't clear from its name.

It's obviously modifying ModifiedUserSurfacedPermissionOptions, but it's not clear WHAT modifications are being made or WHY the modifications are being made.

The API for the function is also unexpected. I would have expected something like:

($ReadOnlyArray<UserSurfacedPermissionOption>, ThreadType) => $ReadOnlyArray<ModifiedUserSurfacedPermissionOption>

That would keep things as general as possible, accepting only the necessary inputs.

Is this function specific to the CreateRolesModal component? If it's going to live in a utils file, it should have a clear name and API.


Here are my suggestions:

  1. Simplify the API. The function should accept UserSurfacedPermissionOptions and a ThreadType, and return ModifiedUserSurfacedPermissionOptions.
  1. Rename the function to more accurately reflect the modifications it makes. If it's hard to encapsulate the two modifications (filtering and adding statements) in one name, it might make sense to split them into separate functions. This would make the functionality more clear at the callsite (eg CreateRolesModal).
  1. Annotate this utility function with a comment explaining its purpose.

Definitely let me know if I'm missing something here

26–34 ↗(On Diff #28944)

Let's introduce a utility function called something like applicablePermissionsForThreadType or filterPermissionsByThreadType to contain this logic. That way it can be expanded/reused in the future for other threadTypes/permissions/etc.

We could maybe go with a similar approach to what we use in rawThreadInfoFromServerThreadInfo:

ae611c.png (762×1 px, 126 KB)

where we map thread types to a list of permissions to be excluded

38–49 ↗(On Diff #28944)

Are these statements actually going to be used for anything? Or are they just to appease the EnumSettingsOption API on web?

If it's just to fit the API, we should see if we can change it. That'll also bring more cross-platform consistency to EnumSettingsOption.

Regardless, this functionality should be encapsulated in a separate function with a clear, descriptive name, rather than being buried within this modifyUserSurfacedPermissionOptions utility.

This revision now requires changes to proceed.Jul 26 2023, 2:19 PM
rohan marked 9 inline comments as done.

Couple of changes here (thanks for suggestions, I agree that it certainly is cleaner now):

  1. I took your advice on using a set instead of an array, so I’ve updated native to prevent any flow errors. In this diff, I changed the use of an array to a set as well.
  2. Make isUserSurfacedPermissionSelected O(1)
  3. Clean up onEnumValuePress
  4. Use the useFilterPermissionOptionsByThreadType hook (now introduced in D8391) to filter out the options based on the thread type, using a better ‘API’ like suggested
  5. Completely remove all logic involving modifying the options for statements to appease EnumSettingsOption. It over complicated the code and also made it harder to maintain for future work I think. Instead, I took the feedback and made isStatementValid and styleStatementBasedOnValidity optional instead, and just passed in a statement (the option’s description)

Let me know if that clears it up!

web/roles/community-roles-modal.react.js
60 ↗(On Diff #28944)

Yeah that definitely makes sense if I was landing diffs individually, I just plan to land the entire stack together so this will never be in production unimplemented

web/roles/create-roles-modal.react.js
43–46 ↗(On Diff #28944)

Got it, thanks for the heads up

Thanks for going through and addressing all the feedback!

web/roles/create-roles-modal.css
10 ↗(On Diff #29097)

Personally would just go with margin-top: 20px; here, but up to you.

This revision is now accepted and ready to land.Jul 28 2023, 11:49 AM
This revision was landed with ongoing or failed builds.Jul 31 2023, 6:15 PM
This revision was automatically updated to reflect the committed changes.