-
Notifications
You must be signed in to change notification settings - Fork 479
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
Section Action Dropdown #18058
Section Action Dropdown #18058
Conversation
❤️ This looks so much better! |
I have two visual nits with this dialog:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great and I love that we get to tear out a bunch of code as part of this change. The new dropdown is a pretty big component - I have some comments there and generally wonder if there are other ways we can break it up a bit.
{i18n.deleteSection()} | ||
</div> | ||
</a> | ||
<BaseDialog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if you leave it at the end of this file, it'd help readability to extract this delete confirmation dialog as its own component. Fortunately there's very little in the way of props you'd need to pass through.
style={{padding:20}} | ||
> | ||
<h2>{i18n.deleteSection()}</h2> | ||
<div>{i18n.deleteSectionConfirm()}</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dialog should include the section name somewhere in its title or description text - otherwise we're depending on the user remembering which section they picked before the dialog opened, which isn't obvious after the fact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also note that we're making a dialog for every section row. For users with a ton of sections it may work better to render the dialog once at the page level and show/hide it based on redux state. After all, you shouldn't be able to show more than one delete dialog at a time.
}; | ||
|
||
onConfirmDelete = () => { | ||
const {removeSection } = this.props; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Unbalanced whitespace.
// While we are embedded in an angular page, reloading is the easiest | ||
// way to pick up roster changes. Once everything is React maybe we | ||
// won't need to do this. | ||
utils.reload(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should be considered out-of-scope of this PR, but it'd be nice to address this comment and allow syncing without a page reload. Might also want some kind of progress or loading spinner intermediate state.
onConfirmDelete = () => { | ||
const {removeSection } = this.props; | ||
const section = this.props.sectionData; | ||
$.ajax({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should handle the intermediate state while this request is in flight gracefully - at least disable the confirm delete button so we can't request this twice, possibly hide the dialog immediately but put the row in a 'pending' state until it gets removed, that sort of thing.
@@ -0,0 +1,57 @@ | |||
@no_mobile | |||
@dashboard_db_access | |||
@pegasus_db_access |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually need both of these tags?
@no_mobile | ||
@dashboard_db_access | ||
@pegasus_db_access | ||
Feature: Using the SectionActionDropdown |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great new tests! I suspect we had some UI tests elsewhere that depended on the buttons we're removing with this change. Have you checked for this?
Also I'll pull this and give it a try. |
I also get different cursors for menu items that are implemented as hyperlinks and those that are implemented with Underline for the current menu item is also a little weird - I think convention for a context menu like this is usually to highlight the currently selected row. IMO that might look better. Obviously defer to Tanya on this. |
import SectionActionBox from "./SectionActionBox"; | ||
|
||
const styles = { | ||
actionButton:{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add cursor:pointer to the chevron button. and maybe a hover style on the button; it doesn't feel super discoverable right now.
@islemaster I think this is ready for another code review, when you get the chance. Thanks! |
apps/src/lib/ui/PopUpMenu.jsx
Outdated
@@ -116,46 +120,84 @@ class MenuBubbleUnwrapped extends Component { | |||
<div style={style} className={className}> | |||
{this.renderMenuItems()} | |||
{/* These elements are used to draw the 'tail' with CSS */} | |||
<span style={tailBorderStyle}/> | |||
<span style={tailFillStyle}/> | |||
{!this.props.minimalStyle && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be nice to have Mark/Poorva choose one style for these. As discussed, the carrot on/off is a reasonable flag, but it feels like we would want these to be the same anyways.
apps/src/lib/ui/PopUpMenu.jsx
Outdated
first: PropTypes.bool, | ||
last: PropTypes.bool, | ||
color: PropTypes.string, | ||
heightDivisor: PropTypes.number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part in particular would be great to not have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading this props list without the component implementation, I don't really know what heightDivisor
does. At least having a comment documenting this prop would be nice, so someone wanting to reuse Item
wouldn't need to read its whole implementation.
}; | ||
|
||
const Tag = href ? 'a' : 'div'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not know you could do this. It feels a bit weird to have a href="null" for a div tag, but apparently this is what we do with Button
.
<PopUpMenu.Item>Option One</PopUpMenu.Item> | ||
<PopUpMenu.Item>Option Two</PopUpMenu.Item> | ||
<PopUpMenu.Item>Option Three</PopUpMenu.Item> | ||
<PopUpMenu.Item onClick={() => {}}>Option One</PopUpMenu.Item> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see these as required in props, why do we need to add these here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They aren't marked as required, but the item will through an exception if an href/onclick is not provided.
}; | ||
|
||
// Menu open | ||
open = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We chatted offline about these functions being able to be pulled apart into a separate component to be used for pop up actions in tables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll probably own in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great progress on this! It's a big change. Very good reuse of color constants and other style constants throughout. I like that we are updating and replacing some older components instead of just producing redundant ones.
My comments break down into style nits, some React gotchas, and I think there's some work we should do now to make testing more thorough. I see Caley has called out some places where we could break large components apart a bit more, I agree that's also a good thing to look at here.
apps/src/lib/ui/PopUpMenu.jsx
Outdated
} | ||
} | ||
|
||
PopUpMenu.MenuBreak = Radium(MenuBreak); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this component get any benefit from Radium? I don't see any style arrays, hover behaviors, or styles that need browser-prefixing.
If not, and especially because this has no props, this would make a great functional stateless component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one ":hover" in here (line 177) so I would be hesitant to remove Radium.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that's on the PopUpMenu.Item
component, not on the PopUpMenu.MenuBreak
component.
apps/src/lib/ui/PopUpMenu.jsx
Outdated
first: PropTypes.bool, | ||
last: PropTypes.bool, | ||
color: PropTypes.string, | ||
heightDivisor: PropTypes.number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading this props list without the component implementation, I don't really know what heightDivisor
does. At least having a comment documenting this prop would be nice, so someone wanting to reuse Item
wouldn't need to read its whole implementation.
sectionName, | ||
removeSection, | ||
toggleSectionHidden, | ||
importOrUpdateRoster} from './teacherSectionsRedux'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We usually avoid aligned indentation, would prefer
import {
sectionCode,
//...
importOrUpdateRoster,
} from './teacherSectionsRedux';
Bonus points if you can find the eslint rule that would enforce and/or autofix this 😁
// Menu open | ||
open = () => { | ||
this.updateMenuLocation(); | ||
window.addEventListener("resize", this.updateMenuLocation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resize events can fire a ton during a window resize, so it can affect performance to do much work in response to them. It would be good to throttle the updateMenuLocation
callback here.
beforeClose = (_, resetPortalState) => { | ||
resetPortalState(); | ||
this.setState({open: false}); | ||
window.setTimeout(() => this.setState({canOpen: true}), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's with the setTimeout(_, 0)
? Would it work to make this the async callback from setState
instead?
And I click selector "#ui-test-edit-section" once I see it | ||
And I press the save button to create a new section | ||
|
||
# This should adequately test section down |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this comment.
Given I am a teacher | ||
And I am on "http://studio.code.org/" | ||
And I create a new section | ||
And I click selector ".fa-chevron-down" once I see it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go ahead and make a "I open the section action dropdown" step that aliases this, all these tests would read better.
And I create a new section | ||
And I click selector ".fa-chevron-down" once I see it | ||
And I click selector "#ui-test-hide-section" once I see it | ||
And I click selector ".ui-test-show-hide" once I see it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could stop and check between these steps that we can't see the section after it's hidden.
And I click selector "#ui-test-hide-section" once I see it | ||
And I click selector ".ui-test-show-hide" once I see it | ||
And I click selector ".fa-chevron-down" once I see it | ||
And I click selector "a:contains('Show Section')" once I see it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, let's assert a final state of the site - check that the section moved back up into the regular sections area.
); | ||
expect(wrapper.text()).to.include(msg.enableMaker()); | ||
}); | ||
|
||
it('renders with enable maker option if maker is available and disabled', () => { | ||
it('renders with disable maker option if maker is available and ensabled', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: ensabled
@islemaster @caleybrock Ready for another review when you get a chance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome. Let's ship this and do incremental improvements afterward. Great work!
👏 👏 so excited for this - it looks good! |
🎉 |
This section table action dropdown removes buttons from the section table and replaces with an expandable list of actions.
@caleybrock is planning to refactor this functionality as she works on react-ing other tables.
[Before]
[After - Google Classroom section]
[After - deletable section]
[Confirm Delete Dialog]