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

Replace Checkboxes List with Stream Pills in Invite Users Modal #26871 #28686

Merged
merged 3 commits into from
Jun 23, 2024

Conversation

sanchi-t
Copy link
Collaborator

@sanchi-t sanchi-t commented Jan 23, 2024

Fixes #26871.

The Invite Users Modal previously featured a list of checkboxes for selecting streams when inviting users. This has been replaced with an input field featuring typeahead and stream pills for streamlined stream selection.

Screenshots and screen captures:

Before:

image

After:

Dark mode:

image
image
image

Light Mode:

image
image
image

Self-review checklist
  • Self-reviewed the changes for clarity and maintainability
    (variable names, code reuse, readability, etc.).

Communicate decisions, questions, and potential concerns.

  • Explains differences from previous plans (e.g., issue description).
  • Highlights technical choices and bugs encountered.
  • Calls out remaining decisions and concerns.
  • Automated tests verify logic where appropriate.

Individual commits are ready for review (see commit discipline).

  • Each commit is a coherent idea.
  • Commit message(s) explain reasoning and motivation for changes.

Completed manual review and testing of the following:

  • Visual appearance of the changes.
  • Responsiveness and internationalization.
  • Strings and tooltips.
  • End-to-end functionality of buttons, interactions and flows.
  • Corner cases, error conditions, and easily imagined bugs.

Comment on lines 73 to 87
export function append_stream(
stream: StreamSubscription,
pill_widget: StreamPillWidget,
display_value: (stream: StreamSubscription) => string,
): void {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is using a parameter, show_stream_sub_size, a better approach than passing a function?

The show_stream_sub_size parameter approach has been employed in a similar PR, #24580.

web/src/add_streams_pill.ts Outdated Show resolved Hide resolved
tools/test-js-with-node Outdated Show resolved Hide resolved
@timabbott
Copy link
Sponsor Member

I guess this is still blocked on migrating pill_typeahead.js to TypeScript? I think there's not much left to do that, as detailed in #frontend.

@timabbott
Copy link
Sponsor Member

@sanchi-t the pill TypeScript work finally got integrated, so it should be possible to rebase and merge this one now!

Copy link
Member

@shubham-padia shubham-padia left a comment

Choose a reason for hiding this comment

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

Looks good visually, thanks @sanchi-t ! I've left a few comments, it also might be worth investing some time into making the commit structure of this PR a bit better

web/src/stream_pill.ts Outdated Show resolved Hide resolved
web/src/pill_typeahead.ts Show resolved Hide resolved
web/src/pill_typeahead.ts Outdated Show resolved Hide resolved
web/src/add_streams_pill.ts Outdated Show resolved Hide resolved
web/templates/invite_user_modal.hbs Show resolved Hide resolved
Copy link
Member

@shubham-padia shubham-padia left a comment

Choose a reason for hiding this comment

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

Left some comments. Moreover, the last 3 commits should be squashed since the css and test changes of a feature should be in the same commit.

web/src/add_streams_pill.ts Outdated Show resolved Hide resolved
display_pill = stream_pill.display_pill;
} else {
display_pill = opts.display_pill;
}
Copy link
Member

Choose a reason for hiding this comment

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

This might be better framed as follows:

    let display_pill: (sub: StreamSubscription) => string = stream_pill.display_pill;
    if (opts.display_pill) {
        display_pill = opts.display_pill;
    }

This makes it easier to read that stream_pill.display_pill is the default display_pill function and we use the opts.display_pill if it exists

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

I'm not entirely sure this version is easier to read; probably the ?? operator might be clearest?

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

So also of note is that this function being patched here is a generic function not limited to just streams, and yet we have a function called display_pill that is only relevant for those? That doesn't make sense.

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Do we need a default value at all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do we need a default value at all?

No, we use display_pill when we call stream_pill.append. We can change the stream_pill.append function such that it accepts an optional parameter for getting stream pill label and it would provide the default value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So also of note is that this function being patched here is a generic function not limited to just streams, and yet we have a function called display_pill that is only relevant for those? That doesn't make sense.

We can rename the function so it indicates its stream specific like stream_display_pill?

I think we need this function in pill_typeahead.ts because pill_typeahead calls stream_pill.append and we need to mention the display value of pill there. It wouldn't been have a problem if we displayed the same format value for stream pill everywhere, but for user invite modal we just want stream name as the display value and not extra information about subscriber count.

Also you suggested to have stream_match_prefix as a parameter which is also specific to streams so i think a function specific to streams should also be alright.

web/src/add_streams_pill.ts Outdated Show resolved Hide resolved
web/src/pill_typeahead.ts Outdated Show resolved Hide resolved
Copy link
Collaborator

@sahil839 sahil839 left a comment

Choose a reason for hiding this comment

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

Posted some comments.

Also, the invite modal is not opened if the user does not have permission to susbcribe others, so that should be fixed.

user_source?: () => User[];
exclude_bots?: boolean;
update_func?: () => void;
help_on_empty_strings?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are these changes required now since set_up_streams function is added?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I am not sure. I thought Tim wanted that stream_match_prefix property for opts in set_up_combined.
Anyway I removed that commit.

web/src/stream_pill.ts Outdated Show resolved Hide resolved
web/src/invite_stream_picker_pill.ts Show resolved Hide resolved
web/src/pill_typeahead.ts Outdated Show resolved Hide resolved
web/src/pill_typeahead.ts Outdated Show resolved Hide resolved
web/src/stream_data.ts Outdated Show resolved Hide resolved
@sahil839
Copy link
Collaborator

Also, I guess the previous approach that you used for translating the text inside the pills [here](#28686 (comment) was fine since variable values are not translated. You can see we use similar methods when text contains user on stream name, one is where we translate the "Already subscribed to {channel}" string in stream_settings_components.js.

@sanchi-t sanchi-t force-pushed the issue-26871 branch 3 times, most recently from 431a244 to ac515ad Compare June 20, 2024 17:26
@sanchi-t
Copy link
Collaborator Author

Also, the invite modal is not opened if the user does not have permission to susbcribe others, so that should be fixed.

What do you mean? If user does not have permission to subscribe other the invite modal should not be opened and that is the current behavior. I am not getting what you mean.

@sanchi-t
Copy link
Collaborator Author

Also, I guess the previous approach that you used for translating the text inside the pills [here](#28686 (comment) was fine since variable values are not translated. You can see we use similar methods when text contains user on stream name, one is where we translate the "Already subscribed to {channel}" string in stream_settings_components.js.

So what do you suggest? Use the previous approach? I think the current approach is better as it is easier/simpler to use stream_pill.create_item_from_stream_name.

@sahil839
Copy link
Collaborator

sahil839 commented Jun 21, 2024

Also, the invite modal is not opened if the user does not have permission to susbcribe others, so that should be fixed.

What do you mean? If user does not have permission to subscribe other the invite modal should not be opened and that is the current behavior. I am not getting what you mean.

It should open and the current behavior is that it does not open.

web/src/stream_pill.ts Outdated Show resolved Hide resolved
web/src/stream_pill.ts Outdated Show resolved Hide resolved
@sahil839
Copy link
Collaborator

So what do you suggest? Use the previous approach? I think the current approach is better as it is easier/simpler to use stream_pill.create_item_from_stream_name

I am not sure. create_item_from_stream_name already accepts show_subscriber_count parameter, so should be easy to just compute the string there itself. It will also help in avoiding adding two extra parameters to StreamPill and other types.

@sanchi-t
Copy link
Collaborator Author

Updates since last review:

  • Used $t for translation (previous approach) instead of adding new properties to StreamPill.
  • The invite modal now opens if user does not have permission to subscribe other.
  • Addressed the review comments.

assert.equal(typeof config.highlighter_html, "function");
assert.equal(typeof config.matcher, "function");
assert.equal(typeof config.sorter, "function");
assert.equal(typeof config.updater, "function");
Copy link
Sponsor Member

@timabbott timabbott Jun 23, 2024

Choose a reason for hiding this comment

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

I'm not really a fan of the testing strategy of doing so much mocking... It's a lot of test code for pretty minimal value.

I guess I can merge this version, but maybe we should discuss in #frontend what would be a better way to unit-test this.

@@ -67,33 +77,43 @@ export function get_user_ids(pill_widget: StreamPillWidget | CombinedPillContain

export function append_stream(
stream: StreamSubscription,
pill_widget: CombinedPillContainer,
pill_widget: StreamPillWidget | CombinedPillContainer,
show_subscriber_count = true,
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

It would be better to do the refactors to add options like this in their own commits, for future reference, since that helps a reviewer model how much risk there is of breaking other pill typeahead components.

Introduce an input field with typeahead functionality, initially
populated with the default streams for the organization.

Fixes zulip#26871.
@timabbott
Copy link
Sponsor Member

timabbott commented Jun 23, 2024

So I did a fairly extensive review, and I think this is basically good to merge. I ended up squashing the last two commits together, since that seemed more readable to me; the new final commit essentially fixed a correctness issue in the previous one. I found one bug, which I'll open as a follow-up issue that should be a high priority -- I don't intend to deploy this to production until it's fixed:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration review Added by maintainers when a PR may be ready for integration. size: XL
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invite users modal: Convert "Streams they should join" to pills
6 participants