Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manage user groups in UserEdit #3450

Merged
merged 24 commits into from
Mar 27, 2019

Conversation

gabrieldutra
Copy link
Member

@gabrieldutra gabrieldutra commented Feb 17, 2019

Description

The idea here is to improve UX for editing user groups by adding an option to manage this in the user edit page.

Some discussion

Changes

  • Update user handler to modify groups (groups seemed not be be a user attr, group_ids was instead)
  • Introduce SelectField in DynamicForm (it may be useful in the future as well)
  • Manage User Groups in UserEdit - 👌

Possible stuff to change depending on comments

  • Refactor Field proptypes (it seems to work, but it's not creating much better check than an Object propType)
  • Separate DynamicForm Fields into smaller components (DynamicFormUploadField, DynamicFormSelectField) instead of render methods

Preview (Admin editing other user)

multiselect-preview

@ghost ghost assigned gabrieldutra Feb 17, 2019
@ghost ghost added the in progress label Feb 17, 2019
@gabrieldutra gabrieldutra marked this pull request as ready for review February 19, 2019 14:40
Copy link
Member

@arikfr arikfr left a comment

Choose a reason for hiding this comment

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

Nice!

  • When we don't render the select field, we should render the list of groups the user belongs to.
  • We shouldn't allow removing all groups from a user, a user should always have at least 1 group association.
  • How hard will it be to add this to the create user form?

Besides that, see comments inline.

Thanks :)

@@ -216,7 +216,7 @@ def post(self, user_id):
user.hash_password(params.pop('password'))
params.pop('old_password')

if 'groups' in params and not self.current_user.has_permission('admin'):
if 'group_ids' in params and not self.current_user.has_permission('admin'):
Copy link
Member

Choose a reason for hiding this comment

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

Need to check that the group ids belong to the current org.

Copy link
Member Author

@gabrieldutra gabrieldutra Feb 19, 2019

Choose a reason for hiding this comment

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

We should rather abort with an error message or simply remove the non-belonging groups? (in frontend side I guess those groups won't even appear, this is more to guarantee the behavior)

  • We shouldn't allow removing all groups from a user, a user should always have at least 1 group association.

I guess I should add the rule here in the backend as well (frontend it was as easy as putting the field required)

Copy link
Member Author

Choose a reason for hiding this comment

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

@arikfr, please check and consider me inexperienced in those parts 😂

initialValue: this.state.groups.filter(group => includes(user.groupIds, group.value))
.map(group => group.value),
} : null,
], isNull).map(field => ({ ...field, readOnly: user.isDisabled }));
Copy link
Member

Choose a reason for hiding this comment

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

Considering that it might take some time to load the groups, maybe have some loading state for the data? I know Ant's Select components have support for this, so it's only a matter of communicating this between the components.

Copy link
Member Author

Choose a reason for hiding this comment

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

Cool, locally it's already done, I also added a "Loading..." placeholder. (better than a whole blank select imo)

@gabrieldutra
Copy link
Member Author

  • When we don't render the select field, we should render the list of groups the user belongs to.

I don't think this should be in the form, but I'll try to come up with a place to put it. (perhaps below or beside the heading as tags).

  • How hard will it be to add this to the create user form?

In case the route for creating a user is pretty similar to this one I would say this will be easy once we migrate the page. I would separate the renderUserInfoForm method into a new component that could be used in both places. (Even without this new component, the use of DynamicForm brings it only a bit more of effort in case there will be different fields)

Copy link
Contributor

@ranbena ranbena left a comment

Choose a reason for hiding this comment

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

I tested the feature on netlify and found the following:

  1. Save not working
    Add group -> save -> refresh page - changes not saved.

  2. Autocomplete not working
    Focus on select ->"admin" group shows in suggestions -> type "a" -> no suggestions (should show "admin")

@gabrieldutra
Copy link
Member Author

  1. Save not working
    Add group -> save -> refresh page - changes not saved.

I suppose this won't work on netlify since there are some backend changes on the user handler.

  1. Autocomplete not working
    Focus on select ->"admin" group shows in suggestions -> type "a" -> no suggestions (should show "admin")

Good catch, I didn't notice this one, by default Ant Select filter works with Option values (in this case they are the group ids). Changing optionFilterProp="children" fixed that though.

Once I fix Arik's comments I'll comment here 🙂

@gabrieldutra
Copy link
Member Author

gabrieldutra commented Feb 21, 2019

A disabled select looks bad, but why not just a tag list?

Can we just render the labels there like you do on the show component?

I had assumed this would be in the form (and considering I'm currently using DynamicForm, that would require a bigger change) 😅 .

Percy view for that:
percy

BTW, I don't know exactly how to handle UserShow jest tests now (after this, it now requires Angular 🤔).

@arikfr
Copy link
Member

arikfr commented Feb 21, 2019

I had assumed this would be in the form (and considering I'm currently using DynamicForm, that would require a bigger change) 😅 .

Two options:

  1. Add a simple content type field, which takes a render function, and renders whatever the function returns.
  2. Just skip DynamicForm here and implement the form directly. Although option 1 sounds simple enough.

BTW, I don't know exactly how to handle UserShow jest tests now (after this, it now requires Angular 🤔).

Why?

@gabrieldutra
Copy link
Member Author

1. Add a simple content type field, which takes a render function, and renders whatever the function returns.

Indeed not a bad idea, I totally forgot about those tricks... Thanks! 🙂

Why?

Because of this. I'm not sure if I'm missing something, but my first guess was that the Group was null because the ngModule didn't init.

@arikfr
Copy link
Member

arikfr commented Feb 23, 2019

Because of this. I'm not sure if I'm missing something, but my first guess was that the Group was null because the ngModule didn't init.

Oh, right. Maybe stub it until we have a better solution?

@arikfr arikfr added Frontend Frontend: React Frontend codebase migration to React labels Feb 26, 2019
@arikfr
Copy link
Member

arikfr commented Mar 12, 2019

Is this ready?

@gabrieldutra
Copy link
Member Author

Is this ready?

Yes, I've just updated with master :)

@gabrieldutra gabrieldutra requested review from arikfr and ranbena March 14, 2019 22:35
Copy link
Contributor

@ranbena ranbena left a comment

Choose a reason for hiding this comment

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

LGTM 👍

One thing perhaps is to swap

<div class="ant-tag other-classnames">
  <a href="">Group Name</a>
</div>

for

<a href="" class="ant-tag other-classnames">Group Name</a>

so that it could have a hover state to better indicate that it's linkable.

@gabrieldutra
Copy link
Member Author

One thing perhaps is to swap [...]

I'm currently using the Tag component for that, so I guess in this case I'd have to stop using it or use css to style it. The first option doesn't seem good as we would use an Antd component class without the component wrapping it. The css option sounds better to me, so how about I add an override to ant.less?

.ant-tag {
  a:hover {
    color: @somecolor
  }
}

@ranbena
Copy link
Contributor

ranbena commented Mar 15, 2019

@gabrieldutra in that case never mind. Leave as is. Not worth the complication. Feel free to merge.

@gabrieldutra gabrieldutra merged commit 2699d24 into getredash:master Mar 27, 2019
harveyrendell pushed a commit to pushpay/redash that referenced this pull request Nov 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Frontend: React Frontend codebase migration to React Frontend
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants