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

Allow users to edit their reviews #3220

Merged
merged 34 commits into from
Sep 26, 2017
Merged

Conversation

kumar303
Copy link
Contributor

@kumar303 kumar303 commented Sep 22, 2017

Fixes mozilla/addons#10789

I focused mainly on mobile styles only since we will do desktop styles in mozilla/addons#10472

Here is the new edit flow. A key difference is that the stars are now editable in the overlay.

edit-review-flow mov

(The blue line at the end is just a glitch in how I converted the movie.)

@@ -244,7 +244,7 @@
"intl": "^1.2.5",
"intl-locales-supported": "^1.0.0",
"jest": "^21.0.2",
"jest-enzyme": "^3.2.0",
"jest-enzyme": "^3.8.3",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This fixed a bug I was seeing in expect()

Copy link
Contributor

Choose a reason for hiding this comment

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

I definitely worked around these in #3202 so the tests aren't as good in there... thanks!

@@ -179,7 +200,7 @@ export class AddonReviewBase extends React.Component {
<input
className="AddonReview-submit"
type="submit"
value={i18n.gettext('Submit review')}
value={i18n.gettext('Update review')}
Copy link
Contributor Author

@kumar303 kumar303 Sep 22, 2017

Choose a reason for hiding this comment

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

It's pretty much always an update whenever you're on this screen. Even the first time you see it, you are editing the review since you have already selected a star rating to get there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any (easy) way to check this though? Like maybe if the existing review text is zero-length? I get that technically they're updating a review after clicking a star, but we call that a rating and it doesn't feel like it. It would be a lot nicer UX to keep "Submit review" for the first time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's not an easy way. I would have to make the internal state of RatingManager more complex and that test suite doesn't test the click-star-then-edit flow in its entirety (due to react-test-utils limitations).

I'll just revert it back to Submit review for now since that makes sense in either case.

onEscapeReviewOverlay = () => {
// Even though an escaped overlay will be hidden, we still have to
// synchronize our show/hide state otherwise we won't be able to
// show the overlay after it has been escaped.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a bit lame since we have a chain of callbacks now. I explained the issue in https://github.com/mozilla/addons-frontend/issues/3222 but I think using callbacks is a quicker fix for now.

store,
...customProps,
};
return shallowUntilTarget(
Copy link
Contributor Author

@kumar303 kumar303 Sep 22, 2017

Choose a reason for hiding this comment

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

Believe it or not I didn't want to spend time converting this whole suite to shallow rendering. However, since I had to refactor the reviews state and be sure I didn't break things along the way, it was really helpful to switch to shallow rendering first. It also turned out to be a nice validation of this shallowUntilTarget pattern because you can see how this component's reliance on mapped state is fully tested now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I really like testing the entire component including the HOC. I'm happy with have that pattern.

@kumar303 kumar303 changed the title Allows users to edit their reviews Allow users to edit their reviews Sep 22, 2017
@codecov-io
Copy link

codecov-io commented Sep 22, 2017

Codecov Report

Merging #3220 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    mozilla/addons-frontend#3220      +/-   ##
==========================================
+ Coverage    95.4%   95.41%   +<.01%     
==========================================
  Files         159      160       +1     
  Lines        2984     3011      +27     
  Branches      588      593       +5     
==========================================
+ Hits         2847     2873      +26     
- Misses        118      119       +1     
  Partials       19       19
Impacted Files Coverage Δ
src/ui/components/OverlayCard/index.js 100% <ø> (ø) ⬆️
src/amo/components/AddonReviewList/index.js 97.91% <100%> (ø)
src/ui/components/Overlay/index.js 100% <100%> (ø) ⬆️
src/amo/reducers/reviews.js 100% <100%> (ø) ⬆️
src/amo/components/AddonReview/index.js 100% <100%> (ø)
src/amo/components/AddonReviewListItem/index.js 100% <100%> (ø)
src/amo/components/Addon/index.js 100% <0%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c3921ae...bf55d18. Read the comment docs.

Copy link
Contributor

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

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

Code looks good but I think the UX of this is a bit off. I think changing the button to more of a link style and giving it more context would be best.

Works well though, so once that's done I think it's set to merge!

@@ -244,7 +244,7 @@
"intl": "^1.2.5",
"intl-locales-supported": "^1.0.0",
"jest": "^21.0.2",
"jest-enzyme": "^3.2.0",
"jest-enzyme": "^3.8.3",
Copy link
Contributor

Choose a reason for hiding this comment

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

I definitely worked around these in #3202 so the tests aren't as good in there... thanks!

import type { SetReviewAction, UserReviewType } from 'amo/actions/reviews';
import type { SubmitReviewParams } from 'amo/api/index';
import type { ApiStateType } from 'core/reducers/api';
import type { ErrorHandler as ErrorHandlerType } from 'core/errorHandler';
import type { ElementEvent } from 'core/types/dom';
import type { DispatchFunc } from 'core/types/redux';

import 'amo/css/AddonReview.scss';
import './styles.scss';
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for tidying this up 😄

@@ -179,7 +200,7 @@ export class AddonReviewBase extends React.Component {
<input
className="AddonReview-submit"
type="submit"
value={i18n.gettext('Submit review')}
value={i18n.gettext('Update review')}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any (easy) way to check this though? Like maybe if the existing review text is zero-length? I get that technically they're updating a review after clicking a star, but we call that a rating and it doesn't feel like it. It would be a lot nicer UX to keep "Submit review" for the first time.

resize: vertical;

@include respond-to("medium") {
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't actually need the quotes here and we've tended not to use them. I only mention it because it'll make it easier to grep for if we're consistent. I'm happy to go all-quotes too, but right now we tend not to use them.

I get that's confusing though.

@@ -55,6 +52,8 @@ export class AddonReviewListBase extends React.Component {
}

loadDataIfNeeded(nextProps?: AddonReviewListProps) {
const lastAddon = this.props.addon;
Copy link
Contributor

Choose a reason for hiding this comment

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

No const { addon: lastAddon } = this.props;? I think I'm finally used to that syntax! 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It only seems necessary to me if you need to destruct multiple variables at once. Otherwise, what's the point?

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough.

let store;

beforeEach(() => {
store = createStore().store;
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, dispatchSignInActions() might be better.

expect(rating).toHaveProp('readOnly', true);
});

it('renders new lines in review bodies', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick but I think it's "newlines", no?

.find(LoadingText)).toHaveLength(1);
});

it('does not render controls when signed in without a review', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I found this spec a bit hard to parse. I got what it meant but I think it might be better rephrased:

it('does not render review controls unless the user left a review', () => {

expect(root.find('.AddonReviewListItem-controls')).toHaveLength(0);
});

it('does not render controls for the wrong user', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe "does not render controls for another user's review"?

onClick={this.onClickToEditReview}
className="AddonReviewListItem-edit-button Button--action Button--small"
>
{i18n.gettext('Edit')}
Copy link
Contributor

Choose a reason for hiding this comment

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

This button could definitely use some more context. I also don't really think it should be a button. I think stylistically looking like a link with a large tap-target would be better. Where there are multiple buttons it might look weird and things like "Report this review" will be link-styled, not button-styled. So I think this should be "Edit my review" and should be an <a> tag instead with link styling.

Changing this to a <a> tag should be fine, I think the only adjustment you'd need would be a preventDefault() for the onClick...

@kumar303
Copy link
Contributor Author

@tofumatt thanks, it should be ready for another review. I gave the Edit anchor tag href="#" because I'm not sure how else to do that. I don't know if it's worth the effort of making a button style that looks like a link.

Copy link
Contributor

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

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

This is good but I just noticed some accessibility issues with the modal.

I'm of the opinion we should ditch modals but I wanted to bring them up:

  1. When navigating with a keyboard, the modal gets activated but keyboard focus isn't changed to the textarea in the review modal. This means the user needs to manually tab over twenty times to get to the review modal. It might be nice to focus the textarea after "Edit my review" is activated.

  2. Esc does not close the modal, at least on my Mac in Nightly.

  3. Clicking to the sides of the modal doesn't close the modal. I need to click above or below it. I'm clicking constantly in this GIF:

2017-09-26 00 53 33

But I think only the first is worth fixing in the scope of this review.

In the future I'd love to ditch modals.

So r+wc if we fix 1. in the above list 😄

@@ -55,6 +52,8 @@ export class AddonReviewListBase extends React.Component {
}

loadDataIfNeeded(nextProps?: AddonReviewListProps) {
const lastAddon = this.props.addon;
Copy link
Contributor

Choose a reason for hiding this comment

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

Fair enough.

@@ -204,7 +173,11 @@ export class AddonReviewListBase extends React.Component {
<CardList>
<ul>
{allReviews.map((review, index) => {
return this.renderReview({ review, key: String(index) });
return (
<li className="AddonReviewList-li" key={String(index)}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure we use this class anywhere anymore (based on its removal from the stylesheet below) and it's a bit awkwardly named anyway. I'd be fine just removing it if it isn't used anywhere.

.AddonReviewListItem {
word-wrap: break-word;

> h3 {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know these are from a previous patch but if it'd be possible to label this with a className and select them directly instead that'd be a bit less fragile. I've liked us not nesting selectors, especially direct selectors like this. I know it's way more verbose but it should help with HTML/CSS refactors.

If not though, it's okay.

@kumar303
Copy link
Contributor Author

I fixed the focus and looked into the other fixes but they weren't straight forward. I think on desktop we can do away with these modals. They were originally designed for mobile so clicking on the sides isn't really an issue (the gutter is pretty small). The modals might still be good UX for mobile screens.

I'll land this and then look at replacing the modal for desktop edits as part of mozilla/addons#10582

The failing tests will be resolved on master soon by #3244

@tofumatt
Copy link
Contributor

I think on desktop we can do away with these modals. They were originally designed for mobile so clicking on the sides isn't really an issue (the gutter is pretty small). The modals might still be good UX for mobile screens.

All sounds good 👍 Thanks!

@kumar303 kumar303 merged commit 5a33c74 into mozilla:master Sep 26, 2017
@kumar303 kumar303 deleted the edit-review-iss3180 branch September 26, 2017 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants